<?php

namespace Tests\Tenant;

use App\Actions\IntegrationVerification\VerifyAutoTraderCoDriver;
use App\Actions\IntegrationVerification\VerifyAutoTraderPartEx;
use App\Actions\IntegrationVerification\VerifyAutoTraderSpecs;
use App\Actions\IntegrationVerification\VerifyBeepBeep;
use App\Actions\IntegrationVerification\VerifyCalltracks;
use App\Actions\IntegrationVerification\VerifyCampaignMonitor;
use App\Actions\IntegrationVerification\VerifyCapPartEx;
use App\Actions\IntegrationVerification\VerifyCapSpecs;
use App\Actions\IntegrationVerification\VerifyCodeWeavers;
use App\Actions\IntegrationVerification\VerifyDmsNavigator;
use App\Actions\IntegrationVerification\VerifyEnquiryMax;
use App\Actions\IntegrationVerification\VerifyEvolutionFunding;
use App\Actions\IntegrationVerification\VerifyHPILookup;
use App\Actions\IntegrationVerification\VerifyHPISpecs;
use App\Actions\IntegrationVerification\VerifyHPIValuation;
use App\Actions\IntegrationVerification\VerifyIvendi;
use App\Actions\IntegrationVerification\VerifyMailChimp;
use App\Actions\IntegrationVerification\VerifyMailServer;
use App\Actions\IntegrationVerification\VerifyMotordat;
use App\Actions\IntegrationVerification\VerifyPinewood;
use App\Actions\IntegrationVerification\VerifyRapidRtc;
use App\Actions\IntegrationVerification\VerifySilverBullet;
use App\Actions\IntegrationVerification\VerifySkoda;
use App\Modules\Stock\Skoda;
use App\Traits\TrackedSeeding;
use App\VehicleSpec\Contracts\VehicleSpecData;
use App\VehicleSpec\Config\MotorCheckConfig;
use App\VehicleSpec\Services\Cap;
use Illuminate\Http\Response;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Http;
use Mockery;
use Mtc\AutomotiveSpecs\VehicleSpecification;
use Mtc\MotorCheck\Services\MotorCheckService;
use Tests\TenantTestCase;

class VerificationTest extends TenantTestCase
{
    use TrackedSeeding;

    public function testTrackedSeed()
    {
        Http::fake([
            "*" => Http::response([], 200),
        ]);
        $this->assertTrue(App::make(VerifyAutoTraderPartEx::class)->verify());
        $this->assertTrue(App::make(VerifyAutoTraderSpecs::class)->verify());
        $this->assertTrue(App::make(VerifyCampaignMonitor::class)->verify());
        $this->assertTrue(App::make(VerifyCapPartEx::class)->verify());
        $this->assertTrue(App::make(VerifyCodeWeavers::class)->verify());
        $this->assertTrue(App::make(VerifyEnquiryMax::class)->verify());
        $this->assertTrue(App::make(VerifyEvolutionFunding::class)->verify());
        $this->assertTrue(App::make(VerifyIvendi::class)->verify());
        $this->assertTrue(App::make(VerifyMailChimp::class)->verify());
        $this->assertTrue(App::make(VerifyMailServer::class)->verify());
        $this->assertTrue(App::make(VerifyRapidRtc::class)->verify());
        $this->assertTrue(App::make(VerifySilverBullet::class)->verify());

        $this->assertInstanceOf(Response::class, App::make(VerifyDmsNavigator::class)->verify());
        $this->assertInstanceOf(Response::class, App::make(VerifyPinewood::class)->verify());
    }

    public function testStubVerifications()
    {
        $this->assertTrue(App::make(VerifyAutoTraderCoDriver::class)->verify());
        $this->assertTrue(App::make(VerifyBeepBeep::class)->verify());
        $this->assertTrue(App::make(VerifyCalltracks::class)->verify());
        $this->assertTrue(App::make(VerifyHPILookup::class)->verify());
        $this->assertTrue(App::make(VerifyHPISpecs::class)->verify());
        $this->assertTrue(App::make(VerifyHPIValuation::class)->verify());
        $this->assertTrue(App::make(VerifyMotordat::class)->verify());
    }

    public function testVerifyCapSpecsSuccess()
    {
        $specData = new VehicleSpecData();
        $specData->technical_data = new Collection(['some' => 'data']);

        $mockCap = Mockery::mock(Cap::class);
        $mockCap->shouldReceive('getSpec')
            ->once()
            ->andReturn($specData);

        $verifier = new VerifyCapSpecs($mockCap);
        $this->assertTrue($verifier->verify());
    }

    public function testVerifyCapSpecsPassesCorrectVehicle()
    {
        $specData = new VehicleSpecData();
        $specData->technical_data = new Collection(['engine' => '2.0L']);

        $mockCap = Mockery::mock(Cap::class);
        $mockCap->shouldReceive('getSpec')
            ->once()
            ->withArgs(function ($vehicle) {
                return $vehicle->cap_id === 83772
                    && $vehicle->registration_number === 'KN23 XMD'
                    && $vehicle->type === 'car';
            })
            ->andReturn($specData);

        $verifier = new VerifyCapSpecs($mockCap);
        $this->assertTrue($verifier->verify());
    }

    public function testVerifyCapSpecsExceptionPropagates()
    {
        $mockCap = Mockery::mock(Cap::class);
        $mockCap->shouldReceive('getSpec')
            ->once()
            ->andThrow(new \Exception('CAP API unavailable'));

        $verifier = new VerifyCapSpecs($mockCap);

        $this->expectException(\Exception::class);
        $this->expectExceptionMessage('CAP API unavailable');
        $verifier->verify();
    }

    public function testVerifySkodaSuccess()
    {
        $mockSkoda = Mockery::mock(Skoda::class);
        $mockSkoda->shouldReceive('endpoint')->once()->andReturn('https://skoda.test');
        $mockSkoda->shouldReceive('fetchVehicles')
            ->once()
            ->with('https://skoda.test')
            ->andReturn(collect(['vehicle1']));

        $verifier = new VerifySkoda($mockSkoda);
        $this->assertTrue($verifier->verify());
    }

    public function testVerifySkodaFailure()
    {
        $mockSkoda = Mockery::mock(Skoda::class);
        $mockSkoda->shouldReceive('endpoint')->once()->andReturn('https://skoda.test');
        $mockSkoda->shouldReceive('fetchVehicles')
            ->once()
            ->with('https://skoda.test')
            ->andReturn(collect([]));

        $verifier = new VerifySkoda($mockSkoda);
        $result = $verifier->verify();
        $this->assertInstanceOf(Response::class, $result);
        $this->assertEquals(422, $result->getStatusCode());
    }

    public function testVerifyMotorCheckSpecsSuccess()
    {
        $mockConfig = Mockery::mock(MotorCheckConfig::class);
        $mockConfig->shouldReceive('clientId')->andReturn('test-client-id');
        $mockConfig->shouldReceive('clientSecret')->andReturn('test-secret');
        $mockConfig->shouldReceive('enabled')->andReturn(true);

        $mockSpec = Mockery::mock(VehicleSpecification::class);
        $mockSpec->UUID = 'test-uuid-123';

        $mockService = Mockery::mock(MotorCheckService::class);
        $mockService->shouldReceive('getCarSpecs')
            ->once()
            ->with('KN23XMD')
            ->andReturn($mockSpec);

        App::instance(MotorCheckService::class, $mockService);

        $verifier = new \App\Actions\IntegrationVerification\VerifyMotorCheckSpecs($mockConfig);
        $this->assertTrue($verifier->verify());
    }

    public function testVerifyMotorCheckSpecsFailure()
    {
        $mockConfig = Mockery::mock(MotorCheckConfig::class);
        $mockConfig->shouldReceive('clientId')->andReturn('test-client-id');
        $mockConfig->shouldReceive('clientSecret')->andReturn('test-secret');
        $mockConfig->shouldReceive('enabled')->andReturn(true);

        $mockSpec = Mockery::mock(VehicleSpecification::class);
        $mockSpec->UUID = null;

        $mockService = Mockery::mock(MotorCheckService::class);
        $mockService->shouldReceive('getCarSpecs')
            ->once()
            ->with('KN23XMD')
            ->andReturn($mockSpec);

        App::instance(MotorCheckService::class, $mockService);

        $verifier = new \App\Actions\IntegrationVerification\VerifyMotorCheckSpecs($mockConfig);
        $this->assertFalse($verifier->verify());
    }
}
