<?php
declare(strict_types=1);

namespace App\Model\Table;

use Cake\ORM\Table;
use Cake\Validation\Validator;

class BookingsTable extends Table
{
    public const STATUS_OPTIONS = [
        'Approved',
        'Rejected',
        'Pending',
        'Confirmed',
        'Picked Up',
        'Collected at Depot',
        'In Transit',
        'Out for Delivery',
        'Delivered',
        'Delivery Failed',
        'Returned',
        'Cancelled',
        'On Hold',
    ];

    public function initialize(array $config): void
    {
        parent::initialize($config);

        $this->setTable('bookings');
        $this->setDisplayField('booking_reference');
        $this->setPrimaryKey('id');

        $this->addBehavior('Timestamp', [
            'created' => 'created',
            'modified' => 'modified',
        ]);
    }

    public function validationDefault(Validator $validator): Validator
    {
        $validator
            ->scalar('booking_reference')
            ->maxLength('booking_reference', 30)
            ->requirePresence('booking_reference', 'create')
            ->notEmptyString('booking_reference');

        $validator
            ->scalar('shipper_name')
            ->maxLength('shipper_name', 120)
            ->requirePresence('shipper_name', 'create')
            ->notEmptyString('shipper_name', 'Please enter shipper full name or company.');

        $validator
            ->email('shipper_email', false, 'Please enter a valid shipper email.')
            ->requirePresence('shipper_email', 'create')
            ->notEmptyString('shipper_email', 'Please enter shipper email.');

        $validator
            ->scalar('shipper_phone')
            ->maxLength('shipper_phone', 20)
            ->requirePresence('shipper_phone', 'create')
            ->notEmptyString('shipper_phone', 'Please enter shipper phone number.')
            ->regex('shipper_phone', '/^[0-9+\s\-()]{8,20}$/', 'Please enter a valid shipper phone number.');

        $validator
            ->scalar('shipper_address')
            ->maxLength('shipper_address', 255)
            ->requirePresence('shipper_address', 'create')
            ->notEmptyString('shipper_address', 'Please enter shipper address.');

        $validator
            ->scalar('receiver_name')
            ->maxLength('receiver_name', 120)
            ->requirePresence('receiver_name', 'create')
            ->notEmptyString('receiver_name', 'Please enter receiver full name or company.');

        $validator
            ->email('receiver_email', false, 'Please enter a valid receiver email.')
            ->requirePresence('receiver_email', 'create')
            ->notEmptyString('receiver_email', 'Please enter receiver email.');

        $validator
            ->scalar('receiver_phone')
            ->maxLength('receiver_phone', 20)
            ->requirePresence('receiver_phone', 'create')
            ->notEmptyString('receiver_phone', 'Please enter receiver phone number.')
            ->regex('receiver_phone', '/^[0-9+\s\-()]{8,20}$/', 'Please enter a valid receiver phone number.');

        $validator
            ->scalar('delivery_address')
            ->maxLength('delivery_address', 255)
            ->requirePresence('delivery_address', 'create')
            ->notEmptyString('delivery_address', 'Please enter delivery address.');

        $validator
            ->scalar('type_of_goods')
            ->maxLength('type_of_goods', 150)
            ->requirePresence('type_of_goods', 'create')
            ->notEmptyString('type_of_goods', 'Please enter type of goods.');

        $validator
            ->scalar('package_type')
            ->maxLength('package_type', 50)
            ->requirePresence('package_type', 'create')
            ->notEmptyString('package_type', 'Please select package type.');

        $validator
            ->integer('number_of_packages', 'Please enter a valid number of packages.')
            ->greaterThanOrEqual('number_of_packages', 1, 'Number of packages must be at least 1.')
            ->requirePresence('number_of_packages', 'create')
            ->notEmptyString('number_of_packages', 'Please enter number of packages.');

        $validator
            ->numeric('weight', 'Please enter a valid weight.')
            ->greaterThan('weight', 0, 'Weight must be greater than 0.')
            ->requirePresence('weight', 'create')
            ->notEmptyString('weight', 'Please enter weight.');

        $validator
            ->numeric('value_of_goods', 'Please enter a valid goods value.')
            ->greaterThanOrEqual('value_of_goods', 0, 'Value of goods cannot be negative.')
            ->requirePresence('value_of_goods', 'create')
            ->notEmptyString('value_of_goods', 'Please enter value of goods.');

        $validator
            ->scalar('mode_of_transport')
            ->maxLength('mode_of_transport', 50)
            ->requirePresence('mode_of_transport', 'create')
            ->notEmptyString('mode_of_transport', 'Please select mode of transport.');

        $validator
            ->scalar('delivery_speed')
            ->maxLength('delivery_speed', 50)
            ->requirePresence('delivery_speed', 'create')
            ->notEmptyString('delivery_speed', 'Please select delivery speed.');

        $validator->allowEmptyString('special_handling');

        $validator
        ->scalar('collection_method')
        ->maxLength('collection_method', 20)
        ->requirePresence('collection_method', 'create')
        ->notEmptyString('collection_method', 'Please select collection method.')
        ->add('collection_method', 'validCollectionMethod', [
            'rule' => function ($value) {
                return in_array($value, ['Pickup', 'Drop Off'], true);
            },
            'message' => 'Invalid collection method selected.',
        ]);

    $validator
        ->scalar('dropoff_location')
        ->maxLength('dropoff_location', 255)
        ->allowEmptyString('dropoff_location');

    $validator
        ->scalar('dropoff_map_link')
        ->maxLength('dropoff_map_link', 500)
        ->allowEmptyString('dropoff_map_link');

    $validator
        ->allowEmptyString('dropoff_note');

    $validator->allowEmptyString('special_handling');

    $validator
        ->date('pickup_date', ['ymd'], 'Please choose a valid pickup date.')
        ->allowEmptyDate('pickup_date')
        ->add('pickup_date', 'pickupDateRequiredForPickup', [
            'rule' => function ($value, $context) {
                $method = $context['data']['collection_method'] ?? 'Pickup';
                if ($method === 'Drop Off') {
                    return true;
                }
                return !empty($value);
            },
            'message' => 'Please choose pickup date.',
        ]);

    $validator
        ->time('pickup_time', 'Please choose a valid pickup time.')
        ->allowEmptyTime('pickup_time')
        ->add('pickup_time', 'pickupTimeRequiredForPickup', [
            'rule' => function ($value, $context) {
                $method = $context['data']['collection_method'] ?? 'Pickup';
                if ($method === 'Drop Off') {
                    return true;
                }
                return !empty($value);
            },
            'message' => 'Please choose pickup time.',
        ]);

        $validator
            ->date('delivery_deadline', ['ymd'], 'Please choose a valid delivery deadline.')
            ->requirePresence('delivery_deadline', 'create')
            ->notEmptyDate('delivery_deadline', 'Please choose delivery deadline.');

        $validator->allowEmptyString('additional_notes');

        $validator
            ->boolean('terms_accepted', 'You must accept the Terms & Conditions.')
            ->requirePresence('terms_accepted', 'create')
            ->notEmptyString('terms_accepted', 'You must accept the Terms & Conditions.')
            ->add('terms_accepted', 'accepted', [
                'rule' => function ($value) {
                    return (bool)$value === true || (string)$value === '1';
                },
                'message' => 'You must accept the Terms & Conditions.',
            ]);

        $validator
            ->scalar('status')
            ->maxLength('status', 50)
            ->allowEmptyString('status')
            ->add('status', 'validStatus', [
                'rule' => function ($value) {
                    if ($value === null || $value === '') {
                        return true;
                    }
                    return in_array($value, self::STATUS_OPTIONS, true);
                },
                'message' => 'Invalid status selected.',
            ]);

        $validator
            ->boolean('archived')
            ->allowEmptyString('archived');

        $validator
            ->scalar('tracking_number')
            ->maxLength('tracking_number', 100)
            ->allowEmptyString('tracking_number');

        $validator
            ->scalar('assigned_courier')
            ->maxLength('assigned_courier', 120)
            ->allowEmptyString('assigned_courier');

        $validator
            ->allowEmptyString('courier_notes');

        return $validator;
    }
}
