<?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\DateUnit;

use BookiFlex\Core\Api\Request\AbstractRequest;
use BookiFlex\Core\Model\DateUnit\DateUnitTypeInterface;
use BookiFlex\Core\Service\DateUnit\DTO\UpdateDateUnits;
use WP_REST_Request;

defined( 'ABSPATH' ) || exit;

class UpdateDateUnitsRequest extends AbstractRequest
{
    public function __construct(
        private readonly int $ratePlanId,
        private readonly int $accommodationTypeId,
        private readonly array $dates,
        private readonly ?array $restrictions,
        private readonly ?array $prices
    ) {
    }

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

        return new self(
            ratePlanId: (int) $params['ratePlan'],
            accommodationTypeId: (int) $params['accommodationType'],
            dates: $params['dates'],
            restrictions: $params['restrictions'] ?? null,
            prices: $params['prices'] ?? null
        );
    }

    /**
     * Convert to domain DTO
     */
    public function toDomainRequest(): UpdateDateUnits
    {
        return new UpdateDateUnits(
            ratePlanId: $this->ratePlanId,
            accommodationTypeId: $this->accommodationTypeId,
            dates: $this->dates,
            restrictions: $this->restrictions,
            prices: $this->prices
        );
    }

    /**
     * Get validation rules for WP REST API
     */
    public static function getValidationRules(): array
    {
        return [
            'ratePlan' => self::positiveIntRule(required: true),
            'accommodationType' => self::positiveIntRule(required: true),
            'dates' => [
                'required' => true,
                'validate_callback' => fn($value) => is_array($value) && count($value) > 0,
                'sanitize_callback' => [self::class, 'sanitizeDates']
            ],
            'restrictions' => [
                'required' => false,
                'default' => null,
                'validate_callback' => fn($value) => is_array($value) || is_null($value),
                'sanitize_callback' => [self::class, 'sanitizeRestrictions']
            ],
            'prices' => [
                'required' => false,
                'default' => null,
                'validate_callback' => fn($value) => is_array($value) || is_null($value),
                'sanitize_callback' => [self::class, 'sanitizePrices']
            ]
        ];
    }

    /**
     * Sanitize dates array
     */
    public static function sanitizeDates(array $dates): array
    {
        return array_map(function ($date) {
            return [
                'dateFrom' => self::sanitizeString($date['dateFrom'] ?? ''),
                'dateTo' => self::sanitizeString($date['dateTo'] ?? ''),
                'mon' => self::sanitizeBool($date['mon'] ?? false),
                'tue' => self::sanitizeBool($date['tue'] ?? false),
                'wed' => self::sanitizeBool($date['wed'] ?? false),
                'thu' => self::sanitizeBool($date['thu'] ?? false),
                'fri' => self::sanitizeBool($date['fri'] ?? false),
                'sat' => self::sanitizeBool($date['sat'] ?? false),
                'sun' => self::sanitizeBool($date['sun'] ?? false),
            ];
        }, $dates);
    }

    /**
     * Sanitize restrictions array
     */
    public static function sanitizeRestrictions(?array $restrictions): ?array
    {
        if (!is_array($restrictions)) {
            return null;
        }

        $sanitized = [];

        // Boolean restrictions
        foreach ([DateUnitTypeInterface::STOP_SALE_TYPE,
                     DateUnitTypeInterface::CTA_TYPE,
                     DateUnitTypeInterface::CTD_TYPE
                 ] as $key) {
            if (array_key_exists($key, $restrictions)) {
                $sanitized[$key] = self::sanitizeBool($restrictions[$key]);
            }
        }

        // Integer restrictions
        foreach ([
            DateUnitTypeInterface::MIN_LOS_TYPE,
                     DateUnitTypeInterface::MAX_LOS_TYPE,
                     DateUnitTypeInterface::MIN_LOS_ARRIVAL_TYPE,
                     DateUnitTypeInterface::MAX_LOS_ARRIVAL_TYPE,
                     DateUnitTypeInterface::MIN_ADV_BOOKING_TYPE,
                     DateUnitTypeInterface::MAX_ADV_BOOKING_TYPE
                 ] as $key) {
            if (array_key_exists($key, $restrictions)) {
                $sanitized[$key] = is_null($restrictions[$key]) ? null : self::sanitizeInt($restrictions[$key]);
            }
        }

        return $sanitized;
    }

    /**
     * Sanitize prices array
     */
    public static function sanitizePrices(?array $prices): ?array
    {
        if (!is_array($prices)) {
            return null;
        }

        return array_map(function ($price) {
            return [
                'variant' => self::sanitizeString($price['variant'] ?? ''),
                'scenario' => self::sanitizeString($price['scenario'] ?? ''),
                'value' => self::sanitizeString($price['value'] ?? ''),
                'cancel' => self::sanitizeBool($price['cancel'] ?? false),
            ];
        }, $prices);
    }
}
