<?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\Api\Request\Pricing;

use BookiFlex\Core\Api\Request\AbstractRequest;
use BookiFlex\Core\Model\DateUnit\RestrictionRulesConfigurator;
use BookiFlex\Core\Provider\LocalTimeZone;
use BookiFlex\Core\Service\OfferFinder\DTO\OfferRequest;
use DateTimeImmutable;
use WP_REST_Request;

defined( 'ABSPATH' ) || exit;

class CalculatePriceRequest extends AbstractRequest
{
    private readonly DateTimeImmutable $checkInDate;
    private readonly DateTimeImmutable $checkOutDate;

    public function __construct(
        DateTimeImmutable|string $checkInDate,
        DateTimeImmutable|string $checkOutDate,
        private readonly int $adults,
        private readonly array $children,
        private readonly int $ratePlanId,
        private readonly int $accommodationTypeId
    ) {
        $this->checkInDate = is_string($checkInDate)
            ? DateTimeImmutable::createFromFormat('Y-m-d', $checkInDate, LocalTimeZone::get())
            : $checkInDate;

        $this->checkOutDate = is_string($checkOutDate)
            ? DateTimeImmutable::createFromFormat('Y-m-d', $checkOutDate, LocalTimeZone::get())
            : $checkOutDate;
    }

    /**
     * Create request from WP REST Request
     */
    public static function fromWpRestRequest(WP_REST_Request $request): self
    {
        $params = $request->get_json_params();

        return new self(
            checkInDate: $params['checkInDate'],
            checkOutDate: $params['checkOutDate'],
            adults: (int) $params['adults'],
            children: $params['children'] ?? [],
            ratePlanId: (int) $params['ratePlanId'],
            accommodationTypeId: (int) $params['accommodationTypeId']
        );
    }

    /**
     * Convert to domain DTO
     */
    public function toDomainRequest(): OfferRequest
    {
        $restrictionConfig = new RestrictionRulesConfigurator(
            false,
            false,
            false,
            false,
            false,
            false,
            false,
            false,
            false
        );

        return new OfferRequest([
            'checkInDate'        => $this->checkInDate->format('Y-m-d'),
            'checkOutDate'       => $this->checkOutDate->format('Y-m-d'),
            'adults'             => $this->adults,
            'children'           => $this->children,
            'ratePlans'          => [$this->ratePlanId],
            'accommodationTypes' => [$this->accommodationTypeId],
        ], $restrictionConfig);
    }

    /**
     * Get validation rules for WP REST API
     */
    public static function getValidationRules(): array
    {
        return [
            'checkInDate' => self::dateRule(required: true),
            'checkOutDate' => self::dateRule(required: true),
            'adults' => [
                'required' => true,
                'type' => 'integer',
                'minimum' => 1,
                'maximum' => 20,
                'sanitize_callback' => fn($value) => (int) $value,
                'validate_callback' => 'rest_validate_request_arg',
            ],
            'children' => [
                'required' => false,
                'type' => 'array',
                'default' => [],
                'items' => [
                    'type' => 'integer',
                    'minimum' => 0,
                    'maximum' => 21,
                ],
                'sanitize_callback' => fn($value) => array_map('intval', $value ?? []),
                'validate_callback' => 'rest_validate_request_arg',
            ],
            'accommodationTypeId' => self::positiveIntRule(required: true),
            'ratePlanId' => self::positiveIntRule(required: true),
        ];
    }

    public function getCheckInDate(): DateTimeImmutable
    {
        return $this->checkInDate;
    }

    public function getCheckOutDate(): DateTimeImmutable
    {
        return $this->checkOutDate;
    }

    public function getAdults(): int
    {
        return $this->adults;
    }

    public function getChildren(): array
    {
        return $this->children;
    }

    public function getRatePlanId(): int
    {
        return $this->ratePlanId;
    }

    public function getAccommodationTypeId(): int
    {
        return $this->accommodationTypeId;
    }
}
