<?php

namespace Tests\Tenant;

use Carbon\Carbon;
use Mtc\MercuryDataModels\BookingAvailability;
use Mtc\MercuryDataModels\BookingAvailabilityHoliday;
use Mtc\MercuryDataModels\Dealership;
use Tests\TenantTestCase;

class BookingAvailabilityModelTest extends TenantTestCase
{
    public function testAllocateHolidaysCreatesRecords()
    {
        $dealership = Dealership::factory()->create();
        $availability = BookingAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'number_of_bays' => 3,
        ]);

        $futureDate1 = Carbon::now()->addWeeks(1)->format('Y-m-d');
        $futureDate2 = Carbon::now()->addWeeks(2)->format('Y-m-d');

        $availability->allocateHolidays([$futureDate1, $futureDate2]);

        $this->assertEquals(2, BookingAvailabilityHoliday::count());
        $dates = BookingAvailabilityHoliday::pluck('holiday_date')
            ->map(fn ($d) => Carbon::parse($d)->format('Y-m-d'))
            ->toArray();
        $this->assertContains($futureDate1, $dates);
        $this->assertContains($futureDate2, $dates);
    }

    public function testAllocateHolidaysDeduplicatesDates()
    {
        $dealership = Dealership::factory()->create();
        $availability = BookingAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'number_of_bays' => 3,
        ]);

        $futureDate = Carbon::now()->addWeeks(1)->format('Y-m-d');

        $availability->allocateHolidays([$futureDate, $futureDate, $futureDate]);

        $this->assertEquals(1, BookingAvailabilityHoliday::count());
    }

    public function testAllocateHolidaysDoesNotDuplicateExistingRecords()
    {
        $dealership = Dealership::factory()->create();
        $availability = BookingAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'number_of_bays' => 3,
        ]);

        $futureDate = Carbon::now()->addWeeks(1)->format('Y-m-d');

        // First allocation
        $availability->allocateHolidays([$futureDate]);
        $this->assertEquals(1, BookingAvailabilityHoliday::count());

        // Second allocation with same date - should not create duplicate
        $availability->allocateHolidays([$futureDate]);
        $this->assertEquals(1, BookingAvailabilityHoliday::count());
    }

    public function testUpcomingHolidaysExcludesPastDates()
    {
        $dealership = Dealership::factory()->create();
        $availability = BookingAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'number_of_bays' => 3,
        ]);

        // Create a past holiday
        BookingAvailabilityHoliday::create([
            'availability_id' => $availability->id,
            'holiday_date' => Carbon::now()->subMonth()->format('Y-m-d'),
            'note' => 'Past holiday',
        ]);

        // Create a future holiday
        BookingAvailabilityHoliday::create([
            'availability_id' => $availability->id,
            'holiday_date' => Carbon::now()->addMonth()->format('Y-m-d'),
            'note' => 'Future holiday',
        ]);

        $upcomingHolidays = $availability->upcomingHolidays;
        $this->assertCount(1, $upcomingHolidays);
        $this->assertEquals('Future holiday', $upcomingHolidays->first()->note);
    }

    public function testAllHolidaysIncludesPastAndFuture()
    {
        $dealership = Dealership::factory()->create();
        $availability = BookingAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'number_of_bays' => 3,
        ]);

        BookingAvailabilityHoliday::create([
            'availability_id' => $availability->id,
            'holiday_date' => Carbon::now()->subMonth()->format('Y-m-d'),
        ]);
        BookingAvailabilityHoliday::create([
            'availability_id' => $availability->id,
            'holiday_date' => Carbon::now()->addMonth()->format('Y-m-d'),
        ]);

        $allHolidays = $availability->holidays;
        $this->assertCount(2, $allHolidays);
    }

    public function testDealershipRelationship()
    {
        $dealership = Dealership::factory()->create(['name' => 'My Dealership']);
        $availability = BookingAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'number_of_bays' => 5,
        ]);

        $this->assertNotNull($availability->dealership);
        $this->assertEquals('My Dealership', $availability->dealership->name);
        $this->assertEquals($dealership->id, $availability->dealership->id);
    }

    public function testDayBooleanCasting()
    {
        $dealership = Dealership::factory()->create();
        $availability = BookingAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'number_of_bays' => 3,
            'mondays' => 1,
            'tuesdays' => 1,
            'wednesdays' => 1,
            'thursdays' => 1,
            'fridays' => 1,
            'saturdays' => 0,
            'sundays' => 0,
        ]);

        $availability->refresh();
        $this->assertTrue($availability->mondays);
        $this->assertTrue($availability->tuesdays);
        $this->assertTrue($availability->wednesdays);
        $this->assertTrue($availability->thursdays);
        $this->assertTrue($availability->fridays);
        $this->assertFalse($availability->saturdays);
        $this->assertFalse($availability->sundays);
    }

    public function testTimeWindowsCastToArray()
    {
        $dealership = Dealership::factory()->create();
        $availability = BookingAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'number_of_bays' => 3,
            'time_windows' => ['09:00', '11:00', '13:00', '15:00'],
        ]);

        $availability->refresh();
        $this->assertIsArray($availability->time_windows);
        $this->assertCount(4, $availability->time_windows);
        $this->assertEquals(['09:00', '11:00', '13:00', '15:00'], $availability->time_windows);
    }

    public function testActiveCastToBoolean()
    {
        $dealership = Dealership::factory()->create();

        $active = BookingAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => 1,
            'number_of_bays' => 3,
        ]);
        $active->refresh();
        $this->assertTrue($active->active);

        $inactive = BookingAvailability::create([
            'dealership_id' => Dealership::factory()->create()->id,
            'active' => 0,
            'number_of_bays' => 3,
        ]);
        $inactive->refresh();
        $this->assertFalse($inactive->active);
    }

    public function testHolidayBelongsToAvailability()
    {
        $dealership = Dealership::factory()->create();
        $availability = BookingAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'number_of_bays' => 3,
        ]);
        $holiday = BookingAvailabilityHoliday::create([
            'availability_id' => $availability->id,
            'holiday_date' => Carbon::now()->addWeek()->format('Y-m-d'),
            'note' => 'Bank Holiday',
        ]);

        $this->assertNotNull($holiday->availability);
        $this->assertEquals($availability->id, $holiday->availability->id);
    }
}
