<?php

namespace Tests\Unit\Services;

use App\Facades\Settings;
use App\Services\AutoTraderHub;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Mtc\MercuryDataModels\Media;
use Mtc\MercuryDataModels\MediaUse;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleFeature;
use Tests\TenantTestCase;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class AutoTraderHubTest extends TestCase
{
    use RefreshDatabase;

    private AutoTraderHub $hub;

    protected $tenancy = true;

    protected function setUp(): void
    {
        parent::setUp();
        $this->hub = new AutoTraderHub();
    }

    public function testSetToken()
    {
        $instance = $this->hub->setToken('my-token');
        $this->assertInstanceOf(AutoTraderHub::class, $instance);

        $this->assertEquals('my-token', $this->invokeMethod($this->hub, 'getToken'));
    }

    public function testInitExportSuccess()
    {
        Http::fake([
            '*' => Http::response(['reference' => 'ref-123'], 200),
        ]);

        $this->hub->setToken('my-token');
        $reference = $this->hub->initExport();

        $this->assertEquals('ref-123', $reference);
    }

    public function testInitExportFails()
    {
        Http::fake([
            '*' => Http::response(['error' => 'fail'], 500),
        ]);

        Log::shouldReceive('error')->once();

        $this->hub->setToken('my-token');

        $this->expectException(\Exception::class);
        $this->hub->initExport();
    }

    public function testBulkExport()
    {
        $vehicles = collect([$this->mockVehicle()]);

        Http::fake([
            '*' => Http::response([], 200),
        ]);

        $this->hub->setToken('my-token');
        $result = $this->hub->bulkExport('ref-001', $vehicles);

        $this->assertTrue($result);
    }

    public function testExportSingleVehicle()
    {
        $vehicle = $this->mockVehicle();

        Http::fake([
            '*' => Http::response([], 200),
        ]);

        $this->hub->setToken('my-token');
        $result = $this->hub->export($vehicle);

        $this->assertTrue($result);
    }

    public function testCreateSiteSuccess()
    {
        Settings::shouldReceive('get')->with('auto-trader-advertiser-id')->andReturn('12345');
        Settings::shouldReceive('update')->with('auto-trader-hub-token', 'abc123')->once();

        config(['services.auto-trader-hub.api_key' => 'key']);
        config(['app.url' => 'https://tenant.example.com']);

        Http::fake([
            '*' => Http::response(['api_token' => 'abc123'], 200),
        ]);

        $response = $this->hub->createSite();
        $this->assertNull($response);
    }

    public function testCreateSiteWithoutApiToken()
    {
        Settings::shouldReceive('get')->with('auto-trader-advertiser-id')->andReturn('12345');
        Settings::shouldReceive('update')->never();

        config(['services.auto-trader-hub.api_key' => 'key']);
        config(['app.url' => 'https://example.com']);

        Http::fake([
            '*' => Http::response(['data' => 'no-token'], 200),
        ]);

        // Asserts it doesn’t break even when token is missing
        $response = $this->hub->createSite();
        $this->assertNull($response);
    }

    private function mockVehicle(): Vehicle
    {
        $vehicle = new Vehicle();
        $vehicle->id = 1;
        $vehicle->auto_trader_id = 'STK123';
        $vehicle->is_new = true;
        $vehicle->registration_number = 'AB12 CDE';
        $vehicle->description = 'Nice car';
        $vehicle->attention_grabber = 'Super quick!';
        $vehicle->is_published = true;
        $vehicle->vin = 'VIN123456';
        $vehicle->make = (object)['name' => 'Ford'];
        $vehicle->model = (object)['name' => 'Fiesta'];
        $vehicle->derivative = 'ST-Line';
        $vehicle->odometer_mi = 12345;
        $vehicle->type = 'car';
        $vehicle->trim = 'Luxury';
        $vehicle->bodyStyle = (object)['name' => 'Hatchback'];
        $vehicle->fuelType = (object)['name' => 'Petrol'];
        $vehicle->transmission = (object)['name' => 'Manual'];
        $vehicle->drivetrain = (object)['name' => 'FWD'];
        $vehicle->seats = 5;
        $vehicle->price = 10995;
        $vehicle->door_count = 5;
        $vehicle->co2 = 99;
        $vehicle->colour = 'Red';
        $vehicle->manufacture_year = 2020;
        $vehicle->first_registration_date = '2020-01-01';
        $vehicle->previous_owner_count = 1;
        $vehicle->engine_size_cc = 1498;
        $vehicle->main_video_url = 'https://video.com/demo';

        $feature1 = new VehicleFeature();
        $feature1->name = 'Air Conditioning';
        $feature1->type = 'comfort';

        $mediaMock = $this->createMock(Media::class);
        $mediaMock->id = 123;
        $mediaMock->auto_trader_id = 'AT456';
        $mediaMock->method('getOriginalUrlAttribute')->willReturn('https://example.com/image.jpg');

        $mediaUseMock = $this->createMock(MediaUse::class);
        $mediaUseMock->method('__get')->with('media')->willReturn($mediaMock);

        $vehicle->features = collect([$feature1]);
        $vehicle->mediaUses = collect([$mediaUseMock]);

        $vehicle->delership = (object)['data' => ['auto-trader-location-id' => 'dealer123']];

        return $vehicle;
    }

    private function invokeMethod(&$object, $methodName, array $parameters = [])
    {
        $reflection = new \ReflectionClass(get_class($object));
        $method = $reflection->getMethod($methodName);
        $method->setAccessible(true);
        return $method->invokeArgs($object, $parameters);
    }
}
