<?php

namespace Tests\Tenant;

use Carbon\Carbon;
use Mtc\MercuryDataModels\DealBuilder\PickupAvailability;
use Mtc\MercuryDataModels\DealBuilder\PickupHoliday;
use Mtc\MercuryDataModels\Dealership;
use Tests\TenantTestCase;
use Tests\UserForTenant;

class DealBuilderPickupControllerTest extends TenantTestCase
{
    use UserForTenant;

    public function testListPickupAvailabilityReturnsDealerships()
    {
        Dealership::factory()->create(['name' => 'Dealer A']);
        Dealership::factory()->create(['name' => 'Dealer B']);

        $response = $this->actingAs($this->getUser())
            ->getJson('/api/deal-pickup-availability');

        $response->assertStatus(200);
        $this->assertCount(2, $response->json());
    }

    public function testListPickupAvailabilityShowsActiveStatus()
    {
        $activeDealership = Dealership::factory()->create(['name' => 'Active Dealer']);
        PickupAvailability::create([
            'dealership_id' => $activeDealership->id,
            'active' => true,
            'max_concurrent_pickups' => 2,
        ]);

        $inactiveDealership = Dealership::factory()->create(['name' => 'Inactive Dealer']);

        $response = $this->actingAs($this->getUser())
            ->getJson('/api/deal-pickup-availability');

        $response->assertStatus(200);
        $dealers = collect($response->json());

        $active = $dealers->firstWhere('id', $activeDealership->id);
        $this->assertEquals('Pick-up active', $active['metaItems']['active']);
        $this->assertTrue($active['has_config']);

        $inactive = $dealers->firstWhere('id', $inactiveDealership->id);
        $this->assertEquals('', $inactive['metaItems']['active']);
        $this->assertFalse($inactive['has_config']);
    }

    public function testShowPickupAvailabilityReturnsDealershipWithConfig()
    {
        $dealership = Dealership::factory()->create(['name' => 'Test Dealer']);
        PickupAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'max_concurrent_pickups' => 3,
            'time_windows' => ['09:00', '11:00', '14:00'],
            'mondays' => true,
            'tuesdays' => true,
            'wednesdays' => true,
            'thursdays' => true,
            'fridays' => true,
            'saturdays' => false,
            'sundays' => false,
            'min_days_in_future' => 1,
            'max_days_in_future' => 60,
        ]);

        $response = $this->actingAs($this->getUser())
            ->getJson('/api/deal-pickup-availability/' . $dealership->id);

        $response->assertStatus(200);

        $this->assertEquals($dealership->id, $response->json('location.id'));
        $this->assertEquals('Test Dealer', $response->json('location.name'));

        $availability = $response->json('availability');
        $this->assertTrue($availability['active']);
        $this->assertEquals(3, $availability['max_concurrent_pickups']);
        $this->assertEquals(['09:00', '11:00', '14:00'], $availability['time_windows']);
        $this->assertTrue($availability['mondays']);
        $this->assertFalse($availability['saturdays']);
        $this->assertEquals(1, $availability['min_days_in_future']);
        $this->assertEquals(60, $availability['max_days_in_future']);
    }

    public function testShowPickupAvailabilityIncludesUpcomingHolidays()
    {
        $dealership = Dealership::factory()->create();
        $availability = PickupAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => true,
            'max_concurrent_pickups' => 1,
        ]);

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

        $response = $this->actingAs($this->getUser())
            ->getJson('/api/deal-pickup-availability/' . $dealership->id);

        $response->assertStatus(200);
        $holidays = $response->json('availability.holidays');
        $this->assertCount(1, $holidays);
    }

    public function testUpdateCreatesNewPickupAvailability()
    {
        $dealership = Dealership::factory()->create();
        $this->assertEquals(0, PickupAvailability::count());

        $response = $this->actingAs($this->getUser())
            ->putJson('/api/deal-pickup-availability/' . $dealership->id, [
                'active' => true,
                'max_concurrent_pickups' => 4,
                'time_windows' => ['09:00', '13:00'],
                'mondays' => true,
                'tuesdays' => true,
                'wednesdays' => true,
                'thursdays' => true,
                'fridays' => true,
                'saturdays' => false,
                'sundays' => false,
                'min_days_in_future' => 2,
                'max_days_in_future' => 90,
                'holidays' => [],
            ]);

        $response->assertStatus(200);
        $this->assertEquals(1, PickupAvailability::count());

        $availability = PickupAvailability::first();
        $this->assertEquals($dealership->id, $availability->dealership_id);
        $this->assertTrue($availability->active);
        $this->assertEquals(4, $availability->max_concurrent_pickups);
        $this->assertEquals(['09:00', '13:00'], $availability->time_windows);
        $this->assertTrue($availability->mondays);
        $this->assertFalse($availability->saturdays);
    }

    public function testUpdateExistingPickupAvailability()
    {
        $dealership = Dealership::factory()->create();
        PickupAvailability::create([
            'dealership_id' => $dealership->id,
            'active' => false,
            'max_concurrent_pickups' => 1,
        ]);

        $response = $this->actingAs($this->getUser())
            ->putJson('/api/deal-pickup-availability/' . $dealership->id, [
                'active' => true,
                'max_concurrent_pickups' => 5,
                'holidays' => [],
            ]);

        $response->assertStatus(200);
        $this->assertEquals(1, PickupAvailability::count());

        $availability = PickupAvailability::first();
        $this->assertTrue($availability->active);
        $this->assertEquals(5, $availability->max_concurrent_pickups);
    }

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

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

        $response = $this->actingAs($this->getUser())
            ->putJson('/api/deal-pickup-availability/' . $dealership->id, [
                'active' => true,
                'max_concurrent_pickups' => 2,
                'holidays' => [$futureDate1, $futureDate2],
            ]);

        $response->assertStatus(200);
        $this->assertEquals(2, PickupHoliday::count());

        $holidayDates = PickupHoliday::pluck('holiday_date')
            ->map(fn ($d) => Carbon::parse($d)->format('Y-m-d'))
            ->toArray();
        $this->assertContains($futureDate1, $holidayDates);
        $this->assertContains($futureDate2, $holidayDates);
    }

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

        $response = $this->actingAs($this->getUser())
            ->putJson('/api/deal-pickup-availability/' . $dealership->id, []);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['active', 'max_concurrent_pickups']);
    }

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

        $response = $this->actingAs($this->getUser())
            ->putJson('/api/deal-pickup-availability/' . $dealership->id, [
                'active' => true,
                'max_concurrent_pickups' => 1,
                'time_windows' => ['not-a-time', '25:99'],
            ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors(['time_windows.0', 'time_windows.1']);
    }
}
