<?php

namespace Tests\Feature\SyncVehicles;

use App\Events\NewVehicleImported;
use App\Events\StockSyncFinished;
use App\Facades\Settings;
use App\TaxonomyMap;
use Database\Seeders\Global\CountrySeeder;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Http;
use Mtc\MercuryDataModels\Dealership;
use Mtc\MercuryDataModels\Setting;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\Notifications\Facades\Notification;
use Tests\DatabaseTestCase;
use Tests\UserForTenant;

class AutoTraderStockImportTest extends DatabaseTestCase
{
    use UserForTenant;

    private string $prefix;

    #[\Override]
    protected function setUp(): void
    {
        parent::setUp();

        $this->prefix = 'https://api-sandbox.autotrader.co.uk';

        Config::set('queue.default', 'sync');
        Settings::shouldReceive('get')->andReturn(null)->byDefault();

        Settings::shouldReceive('get')
            ->with('stock-sync-frequency')
            ->andReturn('every-hour');

        Http::preventStrayRequests();
    }

    public function testAutoTraderStockImportForExistingVehicle()
    {
        Event::fake([StockSyncFinished::class]);

        $dealership = Dealership::factory()->create([
            'data' => ['auto-trader-location-id' => '1234'],
        ]);

        $vehicle = Vehicle::factory()->create([
            'dealership_id' => $dealership->id,
            'vin' => 'test1 vin',
            'stock_provider' => 'autotrader',
            'was_recently_synced' => 0,
            'auto_trader_id' => 'test1'
        ]);

        $vehicle3 = Vehicle::factory()->create([
            'dealership_id' => $dealership->id,
            'vin' => 'test3 vin',
            'stock_provider' => 'autotrader',
            'was_recently_synced' => 0,
            'auto_trader_id' => 'test3'
        ]);

        TaxonomyMap::query()->create([
            'taxonomy_type' => 'master-make',
            'taxonomy_id' => 55,
            'term' => 'Ford',
            'provider' => 'autotrader',
        ]);

        $this->seed(CountrySeeder::class);

        Setting::factory()->create([
            'config_key' => 'stock-auto-trader-enabled',
            'value' => 1
        ]);

        Settings::shouldReceive('get')
            ->with('auto-trader-sync-is-published')
            ->twice()
            ->andReturn(true);

        Settings::shouldReceive('get')
            ->with('stock-auto-trader-sync-video')
            ->twice()
            ->andReturn(true);

        Settings::shouldReceive('get')
            ->with('app-details-country')
            ->times(4)
            ->andReturn(null);

        $this->mockAutotraderHttpResonses();

        // ensures fullSync returns true
        $this->travelTo(now()->setHour(6));

        Artisan::call('sync:vehicles');

        Http::assertSent(fn ($request) => str_contains((string) $request->url(), $this->prefix . '/authenticate'));

        Http::assertSent(fn ($request) => str_contains((string) $request->url(), $this->prefix . '/stock') && str_contains((string) $request->url(), '?'));

        // Assert: vehicle was updated with data from AT
        $this->assertDatabaseHas('vehicles', [
            'auto_trader_id' => 'test1',
            'derivative' => '1.0 test derivative',
            'colour' => 'Black',
            'attention_grabber' => 'attention test1',
        ]);

        Event::assertDispatched(StockSyncFinished::class, fn ($event) => $event->provider === 'auto-trader');

        $notifications = Notification::getAll($this->getUser());
        $this->assertTrue(
            $notifications->contains(fn ($notification) => $notification->severity === 'info'),
            'autotrader'
        );

        $this->assertDatabaseHas('vehicle_attributes', [
            'slug' => 'vat_status',
            'name' => 'VAT Status',
            'type' => 'text',
        ]);

        $this->assertDatabaseHas('vehicle_attribute_values', [
            'owner_id' => $vehicle->id,
            'slug' => 'vat_status',
            'value_text' => 'Inc VAT',
        ]);

        $vehicle->refresh();
        $vehicle3->refresh();

        $this->assertTrue($vehicle->is_vat_applicable);

        $this->assertNotNull($vehicle3);
        $this->assertTrue($vehicle3->is_vat_applicable);

    }

    public function testAutoTraderStockImportForNewVehicle()
    {
        Event::fake([NewVehicleImported::class]);

        Dealership::factory()->create([
            'data' => ['auto-trader-location-id' => 'abc123'],
        ]);

        TaxonomyMap::query()->create([
            'taxonomy_type' => 'master-make',
            'taxonomy_id' => 55,
            'term' => fake()->text(12),
            'provider' => 'autotrader',
        ]);

        $this->seed(CountrySeeder::class);

        Setting::factory()->create([
            'config_key' => 'stock-auto-trader-enabled',
            'value' => 1
        ]);

        $this->mockAutotraderHttpResonses();

        // these settings are specific to JUST these test case
        Settings::shouldReceive('get')
            ->with('stock-auto-trader-sync-images')
            ->once()
            ->andReturn(false);
        Settings::shouldReceive('get')
            ->with('stock-auto-trader-sync-new-vehicles')
            ->times(3)
            ->andReturn(true);
        Settings::shouldReceive('get')
            ->with('app-details-country')
            ->once()
            ->andReturn(null);
        Settings::shouldReceive('get')
            ->with('auto-trader-stock-remove-old-vehicles')
            ->once()
            ->andReturn(true);
        Settings::shouldReceive('get')
            ->with('auto-trader-sync-is-published')
            ->once()
            ->andReturn(true);
        Settings::shouldReceive('get')
            ->with('stock-auto-trader-sync-video')
            ->once()
            ->andReturn(true);
        Settings::shouldReceive('get')
            ->with('app-details-country')
            ->times(2)
            ->andReturn(null);


        // ensures fullSync returns true
        $this->travelTo(now()->setHour(6));

        // Act: Run the command
        Artisan::call('sync:vehicles');

        Http::assertSent(fn ($request) => str_contains((string) $request->url(), $this->prefix . '/authenticate'));

        Http::assertSent(fn ($request) => str_contains((string) $request->url(), $this->prefix . '/stock') && str_contains((string) $request->url(), '?'));

        $this->assertDatabaseHas('vehicles', [
            'auto_trader_id' => 'test2',
            'derivative' => '2.0 test derivative',
            'colour' => 'Blue',
            'attention_grabber' => 'attention test2',
        ]);

        $vehicle = Vehicle::query()->where('auto_trader_id', 'test2')->first();
        $this->assertNotNull($vehicle);
        $this->assertDatabaseHas('vehicle_attribute_values', [
            'owner_id' => $vehicle->id,
            'slug' => 'vat_status',
            'value_text' => 'No VAT',
        ]);

        Event::assertDispatched(NewVehicleImported::class);

        $this->assertFalse($vehicle->is_vat_applicable);

    }

    private function mockAutotraderHttpResonses()
    {
        Http::fake([
            $this->prefix . '/authenticate' => Http::response([
                'access_token' => 'fake-token',
                'expires_in' => 3600,
            ], 200),

            $this->prefix . '/stock?*' => Http::response(
                file_get_contents(base_path('tests/data/stock/autotrader-stock-response.json'), true),
                200
            ),
        ]);
    }

}
