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


declare(strict_types=1);
namespace BookiFlex\Extensions\Cart\Api\Request;

use BookiFlex\Core\Api\Request\AbstractRequest;
use BookiFlex\Extensions\Cart\Service\DTO\CheckoutPreparationDTO;
use WP_Error;
use WP_REST_Request;

defined( 'ABSPATH' ) || exit;

class ConfirmCartRequest extends AbstractRequest
{
    public function __construct(
        private readonly array $customer,
        private readonly ?string $specialRequest,
        private readonly ?string $arrivalTime
    ) {
    }

    public static function fromWpRestRequest(WP_REST_Request $request): self
    {
        $params = $request->get_json_params();

        return new self(
            customer: $params['customer'],
            specialRequest: $params['specialRequest'] ?? null,
            arrivalTime: $params['arrivalTime'] ?? null
        );
    }

    public static function getValidationRules(): array
    {
        return [
            'customer' => [
                'required' => true,
                'validate_callback' => [static::class, 'validateCustomer'],
                'sanitize_callback' => [static::class, 'sanitizeCustomer'],
            ],
            'specialRequest' => [
                'required' => false,
                'validate_callback' => fn($value) => is_string($value) || is_null($value),
                'sanitize_callback' => fn($value) => $value ? mb_substr(self::sanitizeString($value), 0, 500) : null,
            ],
            'arrivalTime' => [
                'required' => false,
                'validate_callback' => fn($value) => is_null($value) || preg_match('/^([01]\d|2[0-3]):([0-5]\d)$/', $value),
                'sanitize_callback' => fn($value) => $value ? self::sanitizeString($value) : null,
            ],
        ];
    }

    public static function validateCustomer($param): bool|WP_Error
    {
        if (!is_array($param)) {
            return new WP_Error('invalid_customer', 'Customer must be an array');
        }

        $errors = [];

        // Validate first name
        if (empty($param['firstName']) || !is_string($param['firstName'])) {
            $errors[] = 'First name is required';
        } elseif (mb_strlen($param['firstName']) > 50) {
            $errors[] = 'First name must not exceed 50 characters';
        }

        // Validate last name
        if (empty($param['lastName']) || !is_string($param['lastName'])) {
            $errors[] = 'Last name is required';
        } elseif (mb_strlen($param['lastName']) > 50) {
            $errors[] = 'Last name must not exceed 50 characters';
        }

        // Validate email
        if (empty($param['email']) || !is_string($param['email'])) {
            $errors[] = 'Email is required';
        } elseif (!filter_var($param['email'], FILTER_VALIDATE_EMAIL)) {
            $errors[] = 'Invalid email format';
        } elseif (mb_strlen($param['email']) > 100) {
            $errors[] = 'Email must not exceed 100 characters';
        }

        // Validate phone (optional)
        if (isset($param['phone']) && $param['phone'] !== '') {
            if (!is_string($param['phone'])) {
                $errors[] = 'Phone must be a string';
            } elseif (mb_strlen($param['phone']) > 20) {
                $errors[] = 'Phone must not exceed 20 characters';
            }
        }

        if (!empty($errors)) {
            return new WP_Error('validation_failed', implode('; ', $errors));
        }

        return true;
    }

    public static function sanitizeCustomer($param): array
    {
        return [
            'firstName' => self::sanitizeString($param['firstName'] ?? ''),
            'lastName' => self::sanitizeString($param['lastName'] ?? ''),
            'email' => sanitize_email($param['email'] ?? ''),
            'phone' => self::sanitizeString($param['phone'] ?? ''),
        ];
    }

    public function getCustomer(): array
    {
        return $this->customer;
    }

    public function getSpecialRequest(): ?string
    {
        return $this->specialRequest;
    }

    public function getArrivalTime(): ?string
    {
        return $this->arrivalTime;
    }

    public function toCheckoutPreparationDTO(): CheckoutPreparationDTO
    {
        return new CheckoutPreparationDTO(
            firstName: $this->customer['firstName'],
            lastName: $this->customer['lastName'],
            email: $this->customer['email'],
            phone: $this->customer['phone'] ?? '',
            specialRequest: $this->specialRequest,
            arrivalTime: $this->arrivalTime
        );
    }
}
