<?php

namespace App\Livewire\Appointments;

use Livewire\Component;
use App\Models\Appointment;
use App\Models\Customer;
use App\Models\Vehicle;
use App\Models\Technician;
use Carbon\Carbon;

class Create extends Component
{
    // Form fields
    public $customer_id = '';
    public $vehicle_id = '';
    public $assigned_technician_id = '';
    public $scheduled_date = '';
    public $scheduled_time = '';
    public $estimated_duration_minutes = 60;
    public $appointment_type = 'maintenance';
    public $service_requested = '';
    public $customer_notes = '';
    public $internal_notes = '';

    // Options
    public $customers = [];
    public $vehicles = [];
    public $technicians = [];
    public $availableTimeSlots = [];

    public $appointmentTypes = [
        'maintenance' => 'Maintenance',
        'repair' => 'Repair',
        'inspection' => 'Inspection',
        'estimate' => 'Estimate',
        'pickup' => 'Pickup',
        'delivery' => 'Delivery'
    ];

    public $durationOptions = [
        30 => '30 minutes',
        60 => '1 hour',
        90 => '1.5 hours',
        120 => '2 hours',
        150 => '2.5 hours',
        180 => '3 hours',
        240 => '4 hours',
    ];

    protected $rules = [
        'customer_id' => 'required|exists:customers,id',
        'vehicle_id' => 'required|exists:vehicles,id',
        'scheduled_date' => 'required|date|after_or_equal:today',
        'scheduled_time' => 'required',
        'estimated_duration_minutes' => 'required|integer|min:15|max:480',
        'appointment_type' => 'required|in:maintenance,repair,inspection,estimate,pickup,delivery',
        'service_requested' => 'required|string|max:500',
        'customer_notes' => 'nullable|string|max:1000',
        'internal_notes' => 'nullable|string|max:1000',
    ];

    protected $messages = [
        'customer_id.required' => 'Please select a customer.',
        'vehicle_id.required' => 'Please select a vehicle.',
        'scheduled_date.required' => 'Please select an appointment date.',
        'scheduled_date.after_or_equal' => 'Appointment date cannot be in the past.',
        'scheduled_time.required' => 'Please select an appointment time.',
        'service_requested.required' => 'Please describe the service requested.',
    ];

    public function mount()
    {
        $this->loadInitialData();
        $this->scheduled_date = Carbon::tomorrow()->format('Y-m-d');
    }

    public function loadInitialData()
    {
        $this->customers = Customer::orderBy('first_name')->orderBy('last_name')->get();
        $this->technicians = Technician::where('status', 'active')->orderBy('first_name')->orderBy('last_name')->get();
    }

    public function updatedCustomerId()
    {
        if ($this->customer_id) {
            $this->vehicles = Vehicle::where('customer_id', $this->customer_id)->get();
            $this->vehicle_id = '';
        } else {
            $this->vehicles = [];
            $this->vehicle_id = '';
        }
    }

    public function updatedScheduledDate()
    {
        if ($this->scheduled_date) {
            $this->loadAvailableTimeSlots();
        }
    }

    public function updatedAssignedTechnicianId()
    {
        if ($this->scheduled_date) {
            $this->loadAvailableTimeSlots();
        }
    }

    public function loadAvailableTimeSlots()
    {
        $date = Carbon::parse($this->scheduled_date);
        $technicianId = $this->assigned_technician_id;
        
        // Generate time slots from 8 AM to 5 PM
        $slots = [];
        $startTime = $date->copy()->setTime(8, 0);
        $endTime = $date->copy()->setTime(17, 0);
        
        while ($startTime->lt($endTime)) {
            $timeSlot = $startTime->format('H:i');
            
            // Check if this time slot is available for the technician
            $isAvailable = true;
            if ($technicianId) {
                $startDateTime = Carbon::parse($this->scheduled_date . ' ' . $timeSlot);
                $endDateTime = $startDateTime->copy()->addMinutes($this->estimated_duration_minutes);
                
                $conflictingAppointments = Appointment::where('assigned_technician_id', $technicianId)
                    ->where(function($query) use ($startDateTime, $endDateTime) {
                        $query->where(function($q) use ($startDateTime, $endDateTime) {
                            // Check if new appointment overlaps with existing ones
                            $q->where(function($subQ) use ($startDateTime, $endDateTime) {
                                // New appointment starts during existing appointment
                                $subQ->where('scheduled_datetime', '<=', $startDateTime)
                                     ->whereRaw('DATE_ADD(scheduled_datetime, INTERVAL estimated_duration_minutes MINUTE) > ?', [$startDateTime]);
                            })->orWhere(function($subQ) use ($startDateTime, $endDateTime) {
                                // New appointment ends during existing appointment
                                $subQ->where('scheduled_datetime', '<', $endDateTime)
                                     ->where('scheduled_datetime', '>=', $startDateTime);
                            });
                        });
                    })
                    ->exists();
                
                $isAvailable = !$conflictingAppointments;
            }
            
            if ($isAvailable) {
                $slots[] = [
                    'value' => $timeSlot,
                    'label' => $startTime->format('g:i A'),
                ];
            }
            
            $startTime->addMinutes(30);
        }
        
        $this->availableTimeSlots = $slots;
    }

    public function save()
    {
        $this->validate();

        try {
            // Check for conflicts one more time
            $scheduledDateTime = Carbon::parse($this->scheduled_date . ' ' . $this->scheduled_time);
            $endDateTime = $scheduledDateTime->copy()->addMinutes($this->estimated_duration_minutes);
            
            if ($this->assigned_technician_id) {
                $conflicts = Appointment::where('assigned_technician_id', $this->assigned_technician_id)
                    ->where(function($query) use ($scheduledDateTime, $endDateTime) {
                        $query->where(function($q) use ($scheduledDateTime, $endDateTime) {
                            // Check if new appointment overlaps with existing ones
                            $q->where(function($subQ) use ($scheduledDateTime, $endDateTime) {
                                // New appointment starts during existing appointment
                                $subQ->where('scheduled_datetime', '<=', $scheduledDateTime)
                                     ->whereRaw('DATE_ADD(scheduled_datetime, INTERVAL estimated_duration_minutes MINUTE) > ?', [$scheduledDateTime]);
                            })->orWhere(function($subQ) use ($scheduledDateTime, $endDateTime) {
                                // New appointment ends during existing appointment
                                $subQ->where('scheduled_datetime', '<', $endDateTime)
                                     ->where('scheduled_datetime', '>=', $scheduledDateTime);
                            })->orWhere(function($subQ) use ($scheduledDateTime, $endDateTime) {
                                // New appointment completely contains existing appointment
                                $subQ->where('scheduled_datetime', '>=', $scheduledDateTime)
                                     ->whereRaw('DATE_ADD(scheduled_datetime, INTERVAL estimated_duration_minutes MINUTE) <= ?', [$endDateTime]);
                            });
                        });
                    })
                    ->exists();
                
                if ($conflicts) {
                    $this->addError('scheduled_time', 'This time slot conflicts with another appointment for the selected technician.');
                    return;
                }
            }

            // Combine date and time into scheduled_datetime
            $scheduledDateTime = Carbon::parse($this->scheduled_date . ' ' . $this->scheduled_time);

            $appointment = Appointment::create([
                'customer_id' => $this->customer_id,
                'vehicle_id' => $this->vehicle_id,
                'assigned_technician_id' => $this->assigned_technician_id ?: null,
                'scheduled_datetime' => $scheduledDateTime,
                'estimated_duration_minutes' => $this->estimated_duration_minutes,
                'appointment_type' => $this->appointment_type,
                'service_requested' => $this->service_requested,
                'customer_notes' => $this->customer_notes,
                'internal_notes' => $this->internal_notes,
                'status' => 'scheduled',
                'created_by' => auth()->id(),
            ]);

            session()->flash('message', 'Appointment scheduled successfully!');
            return redirect()->route('appointments.index');

        } catch (\Exception $e) {
            $this->addError('general', 'Error creating appointment: ' . $e->getMessage());
        }
    }

    public function render()
    {
        return view('livewire.appointments.create')->layout('components.layouts.app', [
            'title' => 'Schedule Appointment'
        ]);
    }
}
