<?php

namespace Tests\Tenant;

use App\Events\VehicleUpdatedFromImport;
use App\Imports\AutoTraderApiToVehicleImport;
use Carbon\Carbon;
use Illuminate\Support\Facades\Event;
use Mtc\MercuryDataModels\Vehicle;
use Tests\TenantTestCase;

class AutoTraderApiToVehicleImportTest extends TenantTestCase
{
    protected AutoTraderApiToVehicleImport $importer;

    #[\Override]
    protected function setUp(): void
    {
        parent::setUp();
        $this->importer = new AutoTraderApiToVehicleImport();
        $this->importer->setDealershipId(1); // example dealership
    }

    public function testExistsReturnsTrueWhenVehicleWithUuidExists()
    {
        Vehicle::factory()->create([
            'stock_provider' => 'auto-trader',
            'uuid' => 'autotrader-uuid-123',
        ]);

        $vehicleData = [
            'metadata' => ['stockId' => 'autotrader-uuid-123'],
            'vehicle' => ['registration' => 'AB12CDE', 'vin' => 'VIN123']
        ];

        $this->assertTrue($this->importer->exists($vehicleData));
    }

    public function testExistsReturnsTrueWhenVehicleWithVinExists()
    {
        Vehicle::factory()->create([
            'stock_provider' => 'auto-trader',
            'vin' => 'VIN123'
        ]);

        $vehicleData = [
            'metadata' => ['stockId' => 'non-matching-id'],
            'vehicle' => ['registration' => 'AB12CDE', 'vin' => 'VIN123']
        ];

        $this->assertTrue($this->importer->exists($vehicleData));
    }

    public function testMapChargeTimesExtractsSlowAndQuickChargeData(): void
    {
        $chargeTimes = [
            [
                'chargerType' => 'Fast Charge',
                'chargerDescription' => '22 kW',
                'chargerSupplyType' => 'AC Three Phase',
                'connectorType' => 'Type 2',
                'startBatteryPercentage' => 0,
                'endBatteryPercentage' => 100,
                'durationMinutes' => 305,
            ],
            [
                'chargerType' => 'Fast Charge',
                'chargerDescription' => '22 kW',
                'chargerSupplyType' => 'AC Three Phase',
                'connectorType' => 'Type 2',
                'startBatteryPercentage' => 10,
                'endBatteryPercentage' => 100,
                'durationMinutes' => 275,
            ],
            [
                'chargerType' => 'Rapid Charge',
                'chargerDescription' => '50 kW',
                'chargerSupplyType' => 'DC',
                'connectorType' => 'CCS',
                'startBatteryPercentage' => 0,
                'endBatteryPercentage' => 80,
                'durationMinutes' => 66,
            ],
            [
                'chargerType' => 'Rapid Charge',
                'chargerDescription' => '50 kW',
                'chargerSupplyType' => 'DC',
                'connectorType' => 'CCS',
                'startBatteryPercentage' => 10,
                'endBatteryPercentage' => 80,
                'durationMinutes' => 58,
            ],
        ];

        $reflection = new \ReflectionMethod($this->importer, 'mapChargeTimes');
        $reflection->setAccessible(true);
        $result = $reflection->invoke($this->importer, $chargeTimes);

        // Slow charge (AC) - picks lowest duration (275 over 305)
        $this->assertEquals(275, $result['battery_charge_time']);
        $this->assertEquals('Type 2', $result['plug_type']);
        $this->assertEquals('22 kW AC Three Phase', $result['battery_slow_charge_description']);

        // Quick charge (DC) - picks lowest duration (58 over 66)
        $this->assertEquals(58, $result['battery_quick_charge_time']);
        $this->assertEquals('CCS', $result['rapid_charge_plug_type']);
        $this->assertEquals(80, $result['battery_quick_charge_level']);
        $this->assertEquals(10, $result['battery_quick_charge_start_level']);
        $this->assertEquals('50 kW DC', $result['battery_quick_charge_description']);
    }

    public function testMapChargeTimesReturnsEmptyArrayWhenNoData(): void
    {
        $reflection = new \ReflectionMethod($this->importer, 'mapChargeTimes');
        $reflection->setAccessible(true);

        $this->assertEmpty($reflection->invoke($this->importer, []));
    }

    /**
     * AUTO-1653: a SOLD vehicle whose AutoTrader record has not been updated for over a week
     * is stale and should be skipped on update.
     */
    public function testIsSoldAndStaleReturnsTrueForSoldVehicleNotUpdatedForOverAWeek(): void
    {
        $this->assertTrue($this->invokeIsSoldAndStale([
            'metadata' => [
                'lifecycleState' => 'SOLD',
                'lastUpdated' => Carbon::now()->subDays(8)->toIso8601String(),
            ],
        ]));
    }

    public function testIsSoldAndStaleReturnsFalseForSoldVehicleUpdatedWithinAWeek(): void
    {
        $this->assertFalse($this->invokeIsSoldAndStale([
            'metadata' => [
                'lifecycleState' => 'SOLD',
                'lastUpdated' => Carbon::now()->subDays(6)->toIso8601String(),
            ],
        ]));
    }

    public function testIsSoldAndStaleReturnsFalseForNonSoldVehicleEvenWhenStale(): void
    {
        $this->assertFalse($this->invokeIsSoldAndStale([
            'metadata' => [
                'lifecycleState' => 'FORECOURT',
                'lastUpdated' => Carbon::now()->subDays(30)->toIso8601String(),
            ],
        ]));
    }

    public function testIsSoldAndStaleReturnsFalseWhenLastUpdatedMissingOrUnparseable(): void
    {
        $this->assertFalse($this->invokeIsSoldAndStale([
            'metadata' => ['lifecycleState' => 'SOLD'],
        ]));

        $this->assertFalse($this->invokeIsSoldAndStale([
            'metadata' => ['lifecycleState' => 'SOLD', 'lastUpdated' => 'not-a-date'],
        ]));
    }

    /**
     * AUTO-1653: the guard is wired into update() - a stale SOLD payload must leave the
     * existing vehicle untouched (no fields changed, no update event dispatched).
     */
    public function testUpdateSkipsStaleSoldVehicle(): void
    {
        Event::fake([VehicleUpdatedFromImport::class]);

        $vehicle = Vehicle::factory()->create([
            'stock_provider' => 'auto-trader',
            'price' => 12345,
            'was_recently_synced' => false,
        ]);

        $this->importer->update([
            'metadata' => [
                'stockId' => 'stock-1',
                'lifecycleState' => 'SOLD',
                'lastUpdated' => Carbon::now()->subDays(8)->toIso8601String(),
            ],
            'adverts' => ['retailAdverts' => ['suppliedPrice' => ['amountGBP' => 99999]]],
        ], $vehicle->id);

        $vehicle->refresh();

        $this->assertSame(12345, (int) $vehicle->price);
        $this->assertFalse((bool) $vehicle->was_recently_synced);
        Event::assertNotDispatched(VehicleUpdatedFromImport::class);
    }

    private function invokeIsSoldAndStale(array $vehicleData): bool
    {
        $reflection = new \ReflectionMethod($this->importer, 'isSoldAndStale');
        $reflection->setAccessible(true);

        return $reflection->invoke($this->importer, $vehicleData);
    }
}
