<?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\ORM\Typecast;

use BookiFlex\Core\Admin\CPT\CancellationPolicy;
use BookiFlex\Core\Model\CancellationPolicy\CancellationRule;
use Cycle\ORM\Parser\CastableInterface;
use Cycle\ORM\Parser\UncastableInterface;

defined( 'ABSPATH' ) || exit;

class CancellationPolicyTypecast implements CastableInterface, UncastableInterface
{
    public function setRules(array $rules): array
    {
        return $rules;
    }

    public function cast(array $data): array
    {
        $rules = [];
        if (isset($data['predefinedRule'])) {
            $rules[] = $this->preparePredefinedRule(
                $data['predefinedRule'],
                isset($data['strictTimeWindow']) ? (int) $data['strictTimeWindow'] : 168,
                isset($data['strictPenaltyPercent']) ? (int) $data['strictPenaltyPercent'] : 100
            );
        }

        $data['rules'] = $rules;

        return $data;
    }

    public function uncast(array $data): array
    {
        return $data;
    }

    private function preparePredefinedRule(
        string $predefinedRule,
        int $strictTimeWindow = 168,
        int $strictPenaltyPercent = 100
    ): CancellationRule {
        return match ($predefinedRule) {
            CancellationPolicy::RULE_FULLY_FLEXIBLE => CancellationRule::createFullyFlexible(),
            CancellationPolicy::RULE_STRICT => CancellationRule::createStrict($strictTimeWindow, $strictPenaltyPercent),
            CancellationPolicy::RULE_FIRST_NIGHT => CancellationRule::createFirstNightPenalty(),
            CancellationPolicy::RULE_NON_REFUNDABLE => CancellationRule::createNonRefundable(),
            default => throw new \InvalidArgumentException('Invalid predefined rule: ' . $predefinedRule),
        };
    }
}
