<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Carbon\Carbon;

class CreateVisitRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     */
    public function rules(): array
    {
        $timeRegex = '/^(0?[1-9]|1[0-2]):[0-5][0-9] (AM|PM)$/';

        return [
            // Host visitor information
            'hostVisitor' => 'required|array',
            'hostVisitor.name' => 'required|string|max:255',
            'hostVisitor.email' => 'required|email|max:255',
            'hostVisitor.phone' => 'required|string|max:20',
            'hostVisitor.location' => 'required|exists:locations,id',

            // Visit details
            'mainVisitorEmail' => 'required|email|max:255',
            'visitReason' => 'required|string|min:10|max:1000',
            'meetingType' => 'required|in:single,multiple',

            // Single day meeting
            'date' => 'required_if:meetingType,single|date|after_or_equal:today',
            'startTime' => ['required_if:meetingType,single', 'string', 'regex:' . $timeRegex],
            'endTime' => ['required_if:meetingType,single', 'string', 'regex:' . $timeRegex],

            // Multiple day meeting
            'dateFrom' => 'required_if:meetingType,multiple|date|after_or_equal:today',
            'dateTo' => 'required_if:meetingType,multiple|date|after:dateFrom',
        ];
    }

    /**
     * Configure the validator instance.
     */
    public function withValidator($validator)
    {
        $validator->after(function ($validator) {
            if ($this->meetingType === 'single' && $this->startTime && $this->endTime) {
                // Parse time strings (e.g., "09:00 AM")
                $startTime = $this->parseTime($this->startTime);
                $endTime = $this->parseTime($this->endTime);

                if (!$startTime || !$endTime) {
                    $validator->errors()->add('time', 'Invalid time format');
                    return;
                }

                // Check business hours (8 AM - 6 PM)
                if ($startTime['hour24'] < 8 || $endTime['hour24'] > 18) {
                    $validator->errors()->add('time', 'Meeting time must be between 8 AM and 6 PM');
                }

                // Check end time is after start time
                $startMinutes = ($startTime['hour24'] * 60) + $startTime['minute'];
                $endMinutes = ($endTime['hour24'] * 60) + $endTime['minute'];

                if ($endMinutes <= $startMinutes) {
                    $validator->errors()->add('endTime', 'End time must be after start time');
                }

                // Check if meeting is in the past
                if ($this->date === today()->format('Y-m-d')) {
                    $now = now();
                    $meetingDateTime = Carbon::parse($this->date)->setTime($startTime['hour24'], $startTime['minute']);

                    if ($meetingDateTime < $now) {
                        $validator->errors()->add('time', 'Cannot schedule meeting in the past');
                    }
                }
            } elseif ($this->meetingType === 'multiple') {
                // For multiple day meetings, set default times if not provided
                if (!$this->startTime) {
                    $this->merge(['startTime' => '08:00 AM']);
                }
                if (!$this->endTime) {
                    $this->merge(['endTime' => '06:00 PM']);
                }
            }
        });
    }

    /**
     * Parse time string from "HH:MM AM/PM" format
     */
    private function parseTime(string $timeString): ?array
    {
        // Match format like "09:00 AM" or "9:00 PM"
        if (preg_match('/^(0?[1-9]|1[0-2]):([0-5][0-9]) (AM|PM)$/', $timeString, $matches)) {
            $hour = (int)$matches[1];
            $minute = (int)$matches[2];
            $amPm = $matches[3];

            // Convert to 24-hour format
            $hour24 = $this->convertTo24Hour($hour, $amPm);

            return [
                'hour12' => $hour,
                'minute' => $minute,
                'amPm' => $amPm,
                'hour24' => $hour24,
            ];
        }

        return null;
    }

    /**
     * Convert 12-hour format to 24-hour format
     */
    private function convertTo24Hour(int $hour, string $amPm): int
    {
        if ($amPm === 'AM') {
            return $hour === 12 ? 0 : $hour;
        } else {
            return $hour === 12 ? 12 : $hour + 12;
        }
    }

    /**
     * Get custom messages for validator errors.
     */
    public function messages(): array
    {
        return [
            'hostVisitor.required' => 'Host visitor information is required',
            'hostVisitor.name.required' => 'Host name is required',
            'hostVisitor.email.required' => 'Host email is required',
            'hostVisitor.email.email' => 'Please provide a valid host email address',
            'hostVisitor.phone.required' => 'Host phone is required',
            'hostVisitor.location.required' => 'Please select a location',
            'hostVisitor.location.exists' => 'Selected location does not exist',
            'mainVisitorEmail.required' => 'Visitor email is required',
            'mainVisitorEmail.email' => 'Please provide a valid email address',
            'visitReason.required' => 'Visit reason is required',
            'visitReason.min' => 'Visit reason must be at least 10 characters',
            'date.after_or_equal' => 'Meeting date must be today or in the future',
            'dateTo.after' => 'End date must be after start date',
            'startTime.regex' => 'Start time must be in format HH:MM AM/PM (e.g., 09:00 AM)',
            'endTime.regex' => 'End time must be in format HH:MM AM/PM (e.g., 05:00 PM)',
        ];
    }
}
