<?php

namespace Tests\Tenant;

use App\Console\Commands\RemoveExpiredReservations;
use App\Facades\Settings;
use Carbon\Carbon;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\VehicleReservations\Reservation;
use Tests\TenantTestCase;

class RemoveExpiredReservationsTest extends TenantTestCase
{
    public function testDoesNothingWhenRemoveExpiredSettingIsDisabled()
    {
        Settings::update('sales-reservation-remove-expired', false);
        Settings::update('sales-reservation-expiry-days', 2);

        $vehicle = Vehicle::factory()->create(['is_reserved' => true]);
        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'confirmed_at' => Carbon::now()->subDays(5),
        ]);

        $this->artisan(RemoveExpiredReservations::class)->assertOk();

        $vehicle->refresh();
        $reservation->refresh();
        $this->assertTrue($vehicle->is_reserved);
        $this->assertEquals('confirmed', $reservation->status);
    }

    public function testDoesNothingWhenExpiryDaysSettingIsMissing()
    {
        Settings::update('sales-reservation-remove-expired', true);

        $vehicle = Vehicle::factory()->create(['is_reserved' => true]);
        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'confirmed_at' => Carbon::now()->subDays(5),
        ]);

        $this->artisan(RemoveExpiredReservations::class)->assertOk();

        $vehicle->refresh();
        $reservation->refresh();
        $this->assertTrue($vehicle->is_reserved);
        $this->assertEquals('confirmed', $reservation->status);
    }

    public function testCancelsExpiredConfirmedReservations()
    {
        Settings::update('sales-reservation-remove-expired', true);
        Settings::update('sales-reservation-expiry-days', 2);

        $vehicle = Vehicle::factory()->create(['is_reserved' => true]);
        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'confirmed_at' => Carbon::now()->subDays(3),
        ]);

        $this->artisan(RemoveExpiredReservations::class)->assertOk();

        $reservation->refresh();
        $vehicle->refresh();
        $this->assertEquals('cancelled', $reservation->status);
        $this->assertFalse($vehicle->is_reserved);
    }

    public function testDoesNotCancelNonExpiredReservations()
    {
        Settings::update('sales-reservation-remove-expired', true);
        Settings::update('sales-reservation-expiry-days', 2);

        $vehicle = Vehicle::factory()->create(['is_reserved' => true]);
        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'confirmed_at' => Carbon::now()->subDay(),
        ]);

        $this->artisan(RemoveExpiredReservations::class)->assertOk();

        $reservation->refresh();
        $vehicle->refresh();
        $this->assertEquals('confirmed', $reservation->status);
        $this->assertTrue($vehicle->is_reserved);
    }

    public function testDoesNotCancelNonConfirmedReservations()
    {
        Settings::update('sales-reservation-remove-expired', true);
        Settings::update('sales-reservation-expiry-days', 2);

        $vehicle = Vehicle::factory()->create(['is_reserved' => false]);
        $reservation = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'pending',
            'confirmed_at' => Carbon::now()->subDays(5),
        ]);

        $this->artisan(RemoveExpiredReservations::class)->assertOk();

        $vehicle->refresh();
        $reservation->refresh();
        $this->assertEquals('pending', $reservation->status);
        $this->assertFalse($vehicle->is_reserved);
    }

    public function testCancelsMultipleExpiredReservations()
    {
        Settings::update('sales-reservation-remove-expired', true);
        Settings::update('sales-reservation-expiry-days', 2);

        $vehicle = Vehicle::factory()->create(['is_reserved' => true]);
        $reservation1 = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'confirmed_at' => Carbon::now()->subDays(5),
        ]);
        $reservation2 = Reservation::factory()->create([
            'vehicle_id' => $vehicle->id,
            'status' => 'confirmed',
            'confirmed_at' => Carbon::now()->subDays(3),
        ]);

        $this->artisan(RemoveExpiredReservations::class)->assertOk();

        $reservation1->refresh();
        $reservation2->refresh();
        $vehicle->refresh();
        $this->assertEquals('cancelled', $reservation1->status);
        $this->assertEquals('cancelled', $reservation2->status);
        $this->assertFalse($vehicle->is_reserved);
    }

    public function testOnlyCancelsExpiredAndLeavesNonExpired()
    {
        Settings::update('sales-reservation-remove-expired', true);
        Settings::update('sales-reservation-expiry-days', 2);

        $expiredVehicle = Vehicle::factory()->create(['is_reserved' => true]);
        $expiredReservation = Reservation::factory()->create([
            'vehicle_id' => $expiredVehicle->id,
            'status' => 'confirmed',
            'confirmed_at' => Carbon::now()->subDays(5),
        ]);

        $activeVehicle = Vehicle::factory()->create(['is_reserved' => true]);
        $activeReservation = Reservation::factory()->create([
            'vehicle_id' => $activeVehicle->id,
            'status' => 'confirmed',
            'confirmed_at' => Carbon::now()->subHours(12),
        ]);

        $this->artisan(RemoveExpiredReservations::class)->assertOk();

        $expiredReservation->refresh();
        $expiredVehicle->refresh();
        $this->assertEquals('cancelled', $expiredReservation->status);
        $this->assertFalse($expiredVehicle->is_reserved);

        $activeReservation->refresh();
        $activeVehicle->refresh();
        $this->assertEquals('confirmed', $activeReservation->status);
        $this->assertTrue($activeVehicle->is_reserved);
    }
}
