<?php
/**
 * BookiFlex Core
 *
 * @package    BookiFlex
 * @subpackage Core
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */


declare(strict_types=1);
namespace BookiFlex\Core\Service\StayCostCalculator\Strategy;

use BookiFlex\Core\Model\AccommodationType\Accommodation\AccommodationType;
use BookiFlex\Core\Model\DateUnit\Calculator\{PriceCalculatorFactory, PriceCalculatorInterface};
use BookiFlex\Core\Model\RatePlan\RatePlan;

defined( 'ABSPATH' ) || exit;

/**
 * Determines calculation strategy based on accommodation type and rate plan
 */
class CalculatorStrategyResolver
{
    public function __construct(
        private readonly PriceCalculatorFactory $factory,
        private array $strategyMap = []
    ) {
    }

    /**
     * Determine strategy for specific accommodation and rate plan
     */
    public function resolve(
        AccommodationType $accommodationType,
        RatePlan $ratePlan
    ): PriceCalculatorInterface {
        // Check custom rules
        $key = $this->buildKey($accommodationType, $ratePlan);
        if (isset($this->strategyMap[$key])) {
            $calculator = $this->factory->get($this->strategyMap[$key]);
            if ($calculator !== null) {
                return $calculator;
            }
        }

        // Check by accommodation category
        $category = $accommodationType->getAccommodationCategory();
        if ($category === 'bed' || $category === 'dorm') {
            // For beds use per_person strategy
            $calculator = $this->factory->get('per_person');
            if ($calculator !== null) {
                return $calculator;
            }
        }

        // By default - standard strategy
        return $this->factory->getDefault();
    }

    /**
     * Register custom strategy
     */
    public function registerStrategy(
        AccommodationType $accommodationType,
        RatePlan $ratePlan,
        string $strategyName
    ): void {
        $key = $this->buildKey($accommodationType, $ratePlan);
        $this->strategyMap[$key] = $strategyName;
    }

    private function buildKey(AccommodationType $accommodation, RatePlan $ratePlan): string
    {
        return $accommodation->getId() . ':' . $ratePlan->getId();
    }
}
