<?php

use App\Models\BlockedTime;
use App\Models\Consultation;
use App\Models\WorkingHour;
use Carbon\Carbon;
use Livewire\Volt\Volt;

beforeEach(function () {
    // Setup working hours for weekdays (Sunday-Thursday)
    foreach ([0, 1, 2, 3, 4] as $day) {
        WorkingHour::factory()->create([
            'day_of_week' => $day,
            'start_time' => '09:00',
            'end_time' => '17:00',
            'is_active' => true,
        ]);
    }
});

it('displays current month by default', function () {
    $currentMonth = now()->translatedFormat('F Y');

    Volt::test('availability-calendar')
        ->assertSee($currentMonth);
});

it('navigates to next month', function () {
    $nextMonth = now()->addMonth()->translatedFormat('F Y');

    Volt::test('availability-calendar')
        ->call('nextMonth')
        ->assertSee($nextMonth);
});

it('prevents navigating to past months', function () {
    Volt::test('availability-calendar')
        ->assertSet('year', now()->year)
        ->assertSet('month', now()->month)
        ->call('previousMonth')
        ->assertSet('year', now()->year)
        ->assertSet('month', now()->month);
});

it('handles year rollover when navigating months', function () {
    Carbon::setTestNow(Carbon::create(2024, 12, 15));

    Volt::test('availability-calendar')
        ->assertSet('year', 2024)
        ->assertSet('month', 12)
        ->call('nextMonth')
        ->assertSet('year', 2025)
        ->assertSet('month', 1);

    Carbon::setTestNow();
});

it('loads available slots when date is selected', function () {
    $sunday = Carbon::now()->next(Carbon::SUNDAY)->format('Y-m-d');

    Volt::test('availability-calendar')
        ->call('selectDate', $sunday)
        ->assertSet('selectedDate', $sunday)
        ->assertNotSet('availableSlots', []);
});

it('does not select unavailable dates', function () {
    // Friday is a non-working day in our setup
    $friday = Carbon::now()->next(Carbon::FRIDAY)->format('Y-m-d');

    Volt::test('availability-calendar')
        ->call('selectDate', $friday)
        ->assertSet('selectedDate', null)
        ->assertSet('availableSlots', []);
});

it('clears selection when navigating months', function () {
    $sunday = Carbon::now()->next(Carbon::SUNDAY)->format('Y-m-d');

    Volt::test('availability-calendar')
        ->call('selectDate', $sunday)
        ->assertSet('selectedDate', $sunday)
        ->call('nextMonth')
        ->assertSet('selectedDate', null)
        ->assertSet('availableSlots', []);
});

it('displays RTL layout for Arabic locale', function () {
    app()->setLocale('ar');

    Volt::test('availability-calendar')
        ->assertSeeHtml('dir="rtl"');
});

it('does not select blocked dates', function () {
    $sunday = Carbon::now()->next(Carbon::SUNDAY);
    BlockedTime::factory()->allDay()->create([
        'block_date' => $sunday->toDateString(),
    ]);

    Volt::test('availability-calendar')
        ->call('selectDate', $sunday->toDateString())
        ->assertSet('selectedDate', null);
});

it('does not select fully booked dates', function () {
    $sunday = Carbon::now()->next(Carbon::SUNDAY);
    $slots = ['09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00'];

    foreach ($slots as $slot) {
        Consultation::factory()->approved()->create([
            'booking_date' => $sunday->toDateString(),
            'booking_time' => $slot,
        ]);
    }

    Volt::test('availability-calendar')
        ->call('selectDate', $sunday->toDateString())
        ->assertSet('selectedDate', null);
});

it('shows available legend items', function () {
    Volt::test('availability-calendar')
        ->assertSee(__('booking.available'))
        ->assertSee(__('booking.partial'))
        ->assertSee(__('booking.unavailable'));
});

it('allows selecting partially booked dates', function () {
    $sunday = Carbon::now()->next(Carbon::SUNDAY);
    Consultation::factory()->approved()->create([
        'booking_date' => $sunday->toDateString(),
        'booking_time' => '10:00',
    ]);

    Volt::test('availability-calendar')
        ->call('selectDate', $sunday->toDateString())
        ->assertSet('selectedDate', $sunday->toDateString())
        ->assertNotSet('availableSlots', []);
});

// User Booked Dates Tests
it('accepts bookedDates prop on mount', function () {
    // Use a date in the current month to avoid navigating
    $bookedDate = Carbon::now()->startOfMonth()->addDays(10)->format('Y-m-d');

    Volt::test('availability-calendar', ['bookedDates' => [$bookedDate]])
        ->assertSet('bookedDates', [$bookedDate]);
});

it('prevents selecting user booked dates', function () {
    $sunday = Carbon::now()->next(Carbon::SUNDAY);
    $component = Volt::test('availability-calendar', ['bookedDates' => [$sunday->format('Y-m-d')]]);

    // Navigate to the month containing the Sunday if necessary
    if ($sunday->month !== now()->month || $sunday->year !== now()->year) {
        $component->call('nextMonth');
    }

    $component->call('selectDate', $sunday->format('Y-m-d'))
        ->assertSet('selectedDate', null);
});

it('marks user booked dates with user_booked status in calendar', function () {
    $sunday = Carbon::now()->next(Carbon::SUNDAY);
    $component = Volt::test('availability-calendar', ['bookedDates' => [$sunday->format('Y-m-d')]]);

    // Navigate to the month containing the Sunday if necessary
    if ($sunday->month !== now()->month || $sunday->year !== now()->year) {
        $component->call('nextMonth');
    }

    $calendarDays = $component->viewData('calendarDays');
    $bookedDay = collect($calendarDays)->firstWhere('date', $sunday->format('Y-m-d'));

    expect($bookedDay)->not->toBeNull();
    expect($bookedDay['status'])->toBe('user_booked');
});

it('shows user booked legend when bookedDates is not empty', function () {
    $bookedDate = Carbon::now()->startOfMonth()->addDays(10)->format('Y-m-d');

    Volt::test('availability-calendar', ['bookedDates' => [$bookedDate]])
        ->assertSee(__('booking.user_booked'));
});

it('does not show user booked legend when bookedDates is empty', function () {
    Volt::test('availability-calendar', ['bookedDates' => []])
        ->assertDontSee(__('booking.user_booked'));
});

it('user booked status takes precedence over available status', function () {
    $sunday = Carbon::now()->next(Carbon::SUNDAY);
    $component = Volt::test('availability-calendar', ['bookedDates' => [$sunday->format('Y-m-d')]]);

    // Navigate to the month containing the Sunday if necessary
    if ($sunday->month !== now()->month || $sunday->year !== now()->year) {
        $component->call('nextMonth');
    }

    $calendarDays = $component->viewData('calendarDays');
    $bookedDay = collect($calendarDays)->firstWhere('date', $sunday->format('Y-m-d'));

    expect($bookedDay)->not->toBeNull();
    expect($bookedDay['status'])->toBe('user_booked');
});

it('allows selecting dates not in bookedDates array', function () {
    $sunday = Carbon::now()->next(Carbon::SUNDAY);
    $monday = Carbon::now()->next(Carbon::MONDAY);
    $component = Volt::test('availability-calendar', ['bookedDates' => [$sunday->format('Y-m-d')]]);

    // Navigate to the month containing the Monday if necessary
    if ($monday->month !== now()->month || $monday->year !== now()->year) {
        $component->call('nextMonth');
    }

    $component->call('selectDate', $monday->format('Y-m-d'))
        ->assertSet('selectedDate', $monday->format('Y-m-d'));
});
