<?php

use App\Enums\ConsultationStatus;
use App\Enums\PaymentStatus;
use App\Mail\BookingSubmittedMail;
use App\Mail\NewBookingAdminEmail;
use App\Models\AdminLog;
use App\Models\Consultation;
use App\Models\User;
use App\Services\AvailabilityService;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Livewire\Volt\Component;

new class extends Component
{
    public ?string $selectedDate = null;

    public ?string $selectedTime = null;

    public string $problemSummary = '';

    public bool $showConfirmation = false;

    public function getBookingStatus(): array
    {
        $user = auth()->user();

        $todayBooking = $user->consultations()
            ->whereDate('booking_date', today())
            ->whereIn('status', [ConsultationStatus::Pending, ConsultationStatus::Approved])
            ->first();

        $pendingRequests = $user->consultations()
            ->where('status', ConsultationStatus::Pending)
            ->where('booking_date', '>=', today())
            ->orderBy('booking_date')
            ->get();

        $bookedDates = $user->consultations()
            ->whereIn('status', [ConsultationStatus::Pending, ConsultationStatus::Approved])
            ->where('booking_date', '>=', today())
            ->pluck('booking_date')
            ->map(fn ($d) => $d->format('Y-m-d'))
            ->toArray();

        return [
            'canBookToday' => is_null($todayBooking),
            'todayBooking' => $todayBooking,
            'pendingRequests' => $pendingRequests,
            'bookedDates' => $bookedDates,
        ];
    }

    public function selectSlot(string $date, string $time): void
    {
        $this->selectedDate = $date;
        $this->selectedTime = $time;
    }

    public function clearSelection(): void
    {
        $this->selectedDate = null;
        $this->selectedTime = null;
        $this->showConfirmation = false;
    }

    public function showConfirm(): void
    {
        $this->validate([
            'selectedDate' => ['required', 'date', 'after_or_equal:today'],
            'selectedTime' => ['required'],
            'problemSummary' => ['required', 'string', 'min:20', 'max:2000'],
        ]);

        // Check 1-per-day limit
        $existingBooking = Consultation::query()
            ->where('user_id', auth()->id())
            ->whereDate('booking_date', $this->selectedDate)
            ->whereIn('status', [ConsultationStatus::Pending, ConsultationStatus::Approved])
            ->exists();

        if ($existingBooking) {
            $this->addError('selectedDate', __('booking.already_booked_this_day'));

            return;
        }

        // Verify slot still available
        $service = app(AvailabilityService::class);
        $availableSlots = $service->getAvailableSlots(Carbon::parse($this->selectedDate));

        if (! in_array($this->selectedTime, $availableSlots)) {
            $this->addError('selectedTime', __('booking.slot_no_longer_available'));

            return;
        }

        $this->showConfirmation = true;
    }

    public function submit(): void
    {
        try {
            DB::transaction(function () {
                // Check slot one more time with lock
                $slotTaken = Consultation::query()
                    ->whereDate('booking_date', $this->selectedDate)
                    ->where('booking_time', $this->selectedTime)
                    ->whereIn('status', [ConsultationStatus::Pending, ConsultationStatus::Approved])
                    ->lockForUpdate()
                    ->exists();

                if ($slotTaken) {
                    throw new \Exception(__('booking.slot_taken'));
                }

                // Check 1-per-day again with lock
                $userHasBooking = Consultation::query()
                    ->where('user_id', auth()->id())
                    ->whereDate('booking_date', $this->selectedDate)
                    ->whereIn('status', [ConsultationStatus::Pending, ConsultationStatus::Approved])
                    ->lockForUpdate()
                    ->exists();

                if ($userHasBooking) {
                    throw new \Exception(__('booking.already_booked_this_day'));
                }

                // Create booking
                $consultation = Consultation::create([
                    'user_id' => auth()->id(),
                    'booking_date' => $this->selectedDate,
                    'booking_time' => $this->selectedTime,
                    'problem_summary' => $this->problemSummary,
                    'status' => ConsultationStatus::Pending,
                    'payment_status' => PaymentStatus::NotApplicable,
                ]);

                // Send email to client
                Mail::to(auth()->user())->queue(
                    new BookingSubmittedMail($consultation)
                );

                // Send email to admin
                $admin = User::query()->where('user_type', 'admin')->first();
                if ($admin) {
                    Mail::to($admin)->queue(
                        new NewBookingAdminEmail($consultation)
                    );
                } else {
                    Log::warning('No admin user found to notify about new booking', [
                        'consultation_id' => $consultation->id,
                    ]);
                }

                // Log action
                AdminLog::create([
                    'admin_id' => null,
                    'action' => 'create',
                    'target_type' => 'consultation',
                    'target_id' => $consultation->id,
                    'new_values' => $consultation->toArray(),
                    'ip_address' => request()->ip(),
                    'created_at' => now(),
                ]);
            });

            session()->flash('success', __('booking.submitted_successfully'));
            $this->redirect(route('client.consultations.index'));

        } catch (\Exception $e) {
            $this->addError('selectedTime', $e->getMessage());
            $this->showConfirmation = false;
        }
    }

    public function with(): array
    {
        return $this->getBookingStatus();
    }
}; ?>

<div class="max-w-4xl mx-auto">
    <flux:heading size="xl" class="mb-6 text-xl sm:text-2xl">{{ __('booking.request_consultation') }}</flux:heading>

    {{-- Booking Status Banner --}}
    <div class="mb-6 rounded-lg border p-4 {{ $canBookToday ? 'border-green-200 bg-green-50 dark:border-green-800 dark:bg-green-900/20' : 'border-amber-200 bg-amber-50 dark:border-amber-800 dark:bg-amber-900/20' }}">
        <div class="flex items-start gap-3">
            @if($canBookToday)
                <flux:icon name="check-circle" class="mt-0.5 h-5 w-5 flex-shrink-0 text-green-600 dark:text-green-400" />
                <div>
                    <p class="font-medium text-green-700 dark:text-green-400">{{ __('booking.can_book_today') }}</p>
                </div>
            @else
                <flux:icon name="information-circle" class="mt-0.5 h-5 w-5 flex-shrink-0 text-amber-600 dark:text-amber-400" />
                <div>
                    <p class="font-medium text-amber-700 dark:text-amber-400">{{ __('booking.already_booked_today') }}</p>
                </div>
            @endif
        </div>

        @if($pendingRequests->isNotEmpty())
            <div class="mt-3 border-t border-zinc-200 pt-3 dark:border-zinc-700">
                @if($pendingRequests->count() === 1)
                    <p class="text-sm text-zinc-600 dark:text-zinc-400">
                        {{ __('booking.pending_for_date', ['date' => $pendingRequests->first()->booking_date->format('d/m/Y')]) }}
                    </p>
                @else
                    <p class="text-sm text-zinc-600 dark:text-zinc-400">
                        {{ __('booking.pending_count', ['count' => $pendingRequests->count()]) }}
                    </p>
                    <ul class="mt-1 list-inside list-disc text-sm text-zinc-500 dark:text-zinc-400">
                        @foreach($pendingRequests->take(3) as $request)
                            <li>{{ $request->booking_date->format('d/m/Y') }}</li>
                        @endforeach
                        @if($pendingRequests->count() > 3)
                            <li>...</li>
                        @endif
                    </ul>
                @endif
            </div>
        @endif

        <p class="mt-3 text-xs text-zinc-500 dark:text-zinc-400">
            {{ __('booking.limit_message') }}
        </p>
    </div>

    @if(!$selectedDate || !$selectedTime)
        <!-- Step 1: Calendar Selection -->
        <div class="mt-6">
            <p class="mb-4 text-zinc-600 dark:text-zinc-400">{{ __('booking.select_date_time') }}</p>
            <livewire:availability-calendar :booked-dates="$bookedDates" />
        </div>
    @else
        <!-- Step 2: Problem Summary -->
        <div class="mt-6">
            <!-- Selected Time Display -->
            <div class="bg-amber-50 dark:bg-amber-900/20 p-4 rounded-lg mb-6 border border-amber-200 dark:border-amber-800">
                <div class="flex justify-between items-center">
                    <div>
                        <p class="font-semibold text-zinc-900 dark:text-zinc-100">{{ __('booking.selected_time') }}</p>
                        <p class="text-zinc-600 dark:text-zinc-400">{{ \Carbon\Carbon::parse($selectedDate)->translatedFormat('l, d M Y') }}</p>
                        <p class="text-zinc-600 dark:text-zinc-400">{{ \Carbon\Carbon::parse($selectedTime)->format('g:i A') }}</p>
                    </div>
                    <flux:button size="sm" wire:click="clearSelection">
                        {{ __('common.change') }}
                    </flux:button>
                </div>
            </div>

            @error('selectedDate')
                <flux:callout variant="danger" class="mb-4">
                    {{ $message }}
                </flux:callout>
            @enderror

            @if(!$showConfirmation)
                <!-- Problem Summary Form -->
                <flux:field>
                    <flux:label class="required">{{ __('booking.problem_summary') }}</flux:label>
                    <flux:textarea
                        wire:model="problemSummary"
                        rows="6"
                        placeholder="{{ __('booking.problem_summary_placeholder') }}"
                    />
                    <flux:description>
                        {{ __('booking.problem_summary_help') }}
                    </flux:description>
                    <flux:error name="problemSummary" />
                </flux:field>

                <flux:button
                    wire:click="showConfirm"
                    class="mt-4 w-full sm:w-auto min-h-[44px]"
                    wire:loading.attr="disabled"
                >
                    <span wire:loading.remove wire:target="showConfirm">{{ __('booking.continue') }}</span>
                    <span wire:loading wire:target="showConfirm">{{ __('common.loading') }}</span>
                </flux:button>
            @else
                <!-- Confirmation Step -->
                <flux:callout>
                    <flux:heading size="sm">{{ __('booking.confirm_booking') }}</flux:heading>
                    <p class="text-zinc-600 dark:text-zinc-400">{{ __('booking.confirm_message') }}</p>

                    <div class="mt-4 space-y-2">
                        <p><strong>{{ __('booking.date') }}:</strong>
                            {{ \Carbon\Carbon::parse($selectedDate)->translatedFormat('l, d M Y') }}</p>
                        <p><strong>{{ __('booking.time') }}:</strong>
                            {{ \Carbon\Carbon::parse($selectedTime)->format('g:i A') }}</p>
                        <p><strong>{{ __('booking.duration') }}:</strong> 45 {{ __('common.minutes') }}</p>
                    </div>

                    <div class="mt-4">
                        <p><strong>{{ __('booking.problem_summary') }}:</strong></p>
                        <p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">{{ $problemSummary }}</p>
                    </div>
                </flux:callout>

                <div class="flex flex-col sm:flex-row gap-3 mt-4">
                    <flux:button wire:click="$set('showConfirmation', false)" class="w-full sm:w-auto min-h-[44px] justify-center">
                        {{ __('common.back') }}
                    </flux:button>
                    <flux:button
                        wire:click="submit"
                        variant="primary"
                        wire:loading.attr="disabled"
                        class="w-full sm:w-auto min-h-[44px] justify-center"
                    >
                        <span wire:loading.remove wire:target="submit">{{ __('booking.submit_request') }}</span>
                        <span wire:loading wire:target="submit">{{ __('common.submitting') }}</span>
                    </flux:button>
                </div>

                @error('selectedTime')
                    <flux:callout variant="danger" class="mt-4">
                        {{ $message }}
                    </flux:callout>
                @enderror
            @endif
        </div>
    @endif
</div>
