<?php

namespace Tests\Feature;

use App\Console\Commands\SyncAutoTraderTaxonomies;
use App\Mail\NewVehicleMakesModelsMail;
use App\Master\Models\BodyStyleType;
use App\Master\Models\VehicleMake;
use App\Master\Models\VehicleModel;
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Tests\DatabaseTestCase;

class AutoTraderVehicleSyncTest extends DatabaseTestCase
{
    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function testTriggerSyncProcess()
    {
        $prefix = 'https://api-sandbox.autotrader.co.uk/taxonomy';
        Mail::fake();
        Http::fake([
            $prefix . '/makes*' => $this->makeResponse(),
            $prefix . '/models*' => $this->modelResponse(),
            '*' => Http::response(null, 400),
        ]);

        $command = $this->artisan(SyncAutoTraderTaxonomies::class);
        $command->run();
        $command->assertExitCode(0);

        $this->assertTrue(VehicleMake::query()->where('name', 'Fiat')->exists());
        $this->assertTrue(VehicleMake::query()->where('name', 'Ford')->exists());
        $this->assertTrue(VehicleModel::query()->where('name', 'Fiesta')->exists());
        $this->assertTrue(VehicleModel::query()->where('name', 'Mondeo')->exists());

        Http::assertSent(fn(Request $request) => Str::contains($request->url(), 'makes'));

        Http::assertSent(fn(Request $request) => Str::contains($request->url(), 'models'));

        Mail::assertQueued(NewVehicleMakesModelsMail::class);
    }

    public function testVehicleTypes()
    {
        Config::set('services.auto-trader.merchant_id', 'foo');

        $prefix = 'https://api-sandbox.autotrader.co.uk/taxonomy';
        Mail::fake();
        Http::fake([
            $prefix . '/makes?advertiserId=foo&vehicleType=Car' => $this->makeResponseCar(),
            $prefix . '/makes?advertiserId=foo&vehicleType=Van' => $this->makeResponseVan(),
            $prefix . '/makes?advertiserId=foo&vehicleType=Bike' => $this->makeResponseBike(),
            $prefix . '/models*' => $this->modelResponse(),
            '*' => Http::response(null, 400),
        ]);

        $command = $this->artisan(SyncAutoTraderTaxonomies::class);
        $command->run();
        $command->assertExitCode(0);

        $car_only_makes = VehicleMake::query()
            ->where('cars', true)
            ->where('lcvs', false)
            ->where('motorcycles', false)
            ->pluck('name');

        $van_only_makes = VehicleMake::query()
            ->where('cars', false)
            ->where('lcvs', true)
            ->where('motorcycles', false)
            ->pluck('name');

        $bike_only_makes = VehicleMake::query()
            ->where('cars', false)
            ->where('lcvs', false)
            ->where('motorcycles', true)
            ->pluck('name');

        $car_van_makes = VehicleMake::query()
            ->where('cars', true)
            ->where('lcvs', true)
            ->where('motorcycles', false)
            ->pluck('name');

        $car_bike_makes = VehicleMake::query()
            ->where('cars', true)
            ->where('lcvs', false)
            ->where('motorcycles', true)
            ->pluck('name');

        $this->assertCount(0, $car_only_makes);
        $this->assertCount(1, $van_only_makes);
        $this->assertCount(1, $bike_only_makes);
        $this->assertCount(2, $car_van_makes);
        $this->assertCount(1, $car_bike_makes);

        $this->assertEquals('Iveco', $van_only_makes->first());
        $this->assertEquals('Ducati', $bike_only_makes->first());
        $this->assertEquals('Honda', $car_bike_makes->first());

        $this->assertContains('Fiat', $car_van_makes);
        $this->assertContains('Ford', $car_van_makes);
    }

    public function testBodyTypes()
    {
        Config::set('services.auto-trader.merchant_id', 'foo');

        $prefix = 'https://api-sandbox.autotrader.co.uk/taxonomy';
        Mail::fake();
        Http::fake([
            $prefix . '/bodyTypes?advertiserId=foo&vehicleType=Car' => $this->bodyResponseCar(),
            $prefix . '/bodyTypes?advertiserId=foo&vehicleType=Van' => $this->bodyResponseVan(),
            $prefix . '/bodyTypes?advertiserId=foo&vehicleType=Bike' => $this->bodyResponseBike(),
            $prefix . '/models*' => $this->modelResponse(),
            '*' => Http::response(null, 400),
        ]);

        $command = $this->artisan(SyncAutoTraderTaxonomies::class);
        $command->run();
        $command->assertExitCode(0);

        $car_body_styles = BodyStyleType::query()->where('type', 'car')->pluck('name');
        $van_body_styles = BodyStyleType::query()->where('type', 'lcv')->pluck('name');
        $bike_body_styles = BodyStyleType::query()->where('type', 'motorcycle')->pluck('name');

        $this->assertCount(3, $car_body_styles);
        $this->assertCount(1, $van_body_styles);
        $this->assertCount(2, $bike_body_styles);

        $this->assertContains('saloon', $car_body_styles);
        $this->assertContains('coupe', $car_body_styles);
        $this->assertContains('hatchback', $car_body_styles);
        $this->assertContains('luton', $van_body_styles);
        $this->assertContains('tourer', $bike_body_styles);
        $this->assertContains('scooter', $bike_body_styles);
    }

    private function makeResponse()
    {
        return Http::response([
            "makes" => [
                [
                    "makeId" => "2c9299d1712af419017130a7163969f4",
                    "name" => "Fiat"
                ],
                [
                    "makeId" => "2c9299017130a7163969f4d1712af419",
                    "name" => "Ford"
                ],
            ]
        ]);
    }

    private function modelResponse()
    {
        return Http::response([
            "models" => [
                [
                    "modelId" => "2c9299d1712af419017130a7163969f4",
                    "name" => "Fiesta"
                ],
                [
                    "modelId" => "2c9299017130a7163969f4d1712af419",
                    "name" => "Mondeo"
                ],
            ]

        ]);
    }

    private function makeResponseCar()
    {
        return Http::response([
            "makes" => [
                [
                    "makeId" => 'make_id_fiat',
                    "name" => "Fiat"
                ],
                [
                    "makeId" => 'make_id_ford',
                    "name" => "Ford"
                ],
                [
                    "makeId" => 'make_id_honda',
                    "name" => "Honda"
                ],
            ]
        ]);
    }

    private function makeResponseVan()
    {
        return Http::response([
            "makes" => [
                [
                    "makeId" => 'make_id_fiat',
                    "name" => "Fiat"
                ],
                [
                    "makeId" => 'make_id_ford',
                    "name" => "Ford"
                ],
                [
                    "makeId" => Str::random(),
                    "name" => "Iveco"
                ],
            ]
        ]);
    }

    private function makeResponseBike()
    {
        return Http::response([
            "makes" => [
                [
                    "makeId" => 'make_id_honda',
                    "name" => "Honda"
                ],
                [
                    "makeId" => Str::random(),
                    "name" => "Ducati"
                ],
            ],
        ]);
    }

    private function bodyResponseCar()
    {
        return Http::response([
            "bodyTypes" => [
                [
                    "name" => "saloon"
                ],
                [
                    "name" => "coupe"
                ],
                [
                    "name" => "hatchback"
                ],
            ]
        ]);
    }

    private function bodyResponseVan()
    {
        return Http::response([
            "bodyTypes" => [
                [
                    "name" => "luton"
                ],
            ]
        ]);
    }

    private function bodyResponseBike()
    {
        return Http::response([
            "bodyTypes" => [
                [
                    "name" => "scooter"
                ],
                [
                    "name" => "tourer"
                ],
            ]
        ]);
    }
}
