<?php

namespace Tests\Tenant\Controllers;

use App\Console\Commands\SalesChannelExportCommand;
use App\Facades\Settings;
use App\Jobs\CarGurusExportJob;
use App\Jobs\CarWowExportJob;
use Database\Seeders\Tenant\CarGuruExportSeeder;
use Database\Seeders\Tenant\CarWowExportSeeder;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Queue;
use Mtc\MercuryDataModels\Events\SettingUpdated;
use Mtc\MercuryDataModels\SalesChannelHistory;
use Mtc\MercuryDataModels\SalesChannelRule;
use Tests\TenantTestCase;
use Tests\UserForTenant;

class SalesChannelControllerTest extends TenantTestCase
{
    use UserForTenant;

    protected bool $useTestSettingRepository = false;

    public function testIndex()
    {
        $this->setCarWowCarGuruExportSettings();

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.sales-channels.index'));

        $response->assertStatus(200);
        $this->assertCount(2, $response->json('data'));
        $this->assertTrue(collect($response->json('data'))->pluck('title')->search('CarGuru') !== false);
        $this->assertTrue(collect($response->json('data'))->pluck('title')->search('CarWow') !== false);
    }

    public function testShow()
    {
        $this->setCarWowCarGuruExportSettings();

        SalesChannelHistory::factory(10)->create(['channel' => 'car-gurus']);
        SalesChannelHistory::factory(5)->create(['channel' => 'motors.co.uk']);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.sales-channels.show', 'moto-novo'));
        $response->assertStatus(404);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.sales-channels.show', 'car-gurus'));
        $response->assertStatus(200);
        $this->assertArrayHasKey('name', $response->json());
        $this->assertArrayHasKey('channel', $response->json());
        $this->assertArrayHasKey('logs', $response->json());
        $this->assertCount(10, $response->json('logs'));
    }

    public function testTriggerSalesChannelCommand()
    {
        $this->setCarWowCarGuruExportSettings();

        Queue::fake();
        $this->artisan(SalesChannelExportCommand::class);
        Queue::assertPushed(CarWowExportJob::class);
        Queue::assertPushed(CarGurusExportJob::class);
    }

    public function testUpdateAddConditions()
    {
        $this->setCarWowCarGuruExportSettings();

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.sales-channels.update', 'car-gurus'), [
                'conditions' => [
                    [
                        'value' => [
                            'type' => 'and',
                            'column' => 'cap_id',
                            'operator' => '=',
                            'value' => '12345'
                        ],
                    ],
                ],
            ]);

        $response->assertStatus(200);

        $this->assertCount(1, SalesChannelRule::all());
        $this->assertCount(1, SalesChannelRule::query()->where('channel', '=', 'car-gurus')->get());

        $conditions = SalesChannelRule::query()->where('channel', '=', 'car-gurus')->first()?->conditions;

        $this->assertEquals('cap_id', $conditions[0]['value']['column']);
        $this->assertEquals('12345', $conditions[0]['value']['value']);
    }

    public function testUpdateAmendConditions()
    {
        $this->setCarWowCarGuruExportSettings();

        SalesChannelRule::query()->create([
            'channel' => 'car-gurus',
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'cap_id',
                        'operator' => '=',
                        'value' => '12345'
                    ],
                ],
            ],
        ]);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.sales-channels.update', 'car-gurus'), [
                'conditions' => [
                    [
                        'value' => [
                            'type' => 'and',
                            'column' => 'vrm',
                            'operator' => '=',
                            'value' => 'ABC123'
                        ],
                    ],
                ],
            ]);

        $response->assertStatus(200);

        $this->assertCount(1, SalesChannelRule::all());
        $this->assertCount(1, SalesChannelRule::query()->where('channel', '=', 'car-gurus')->get());

        $conditions = SalesChannelRule::query()->where('channel', '=', 'car-gurus')->first()?->conditions;

        $this->assertCount(1, $conditions);
        $this->assertEquals('vrm', $conditions[0]['value']['column']);
        $this->assertEquals('ABC123', $conditions[0]['value']['value']);
    }

    public function testUpdateRemoveConditions()
    {
        $this->setCarWowCarGuruExportSettings();

        SalesChannelRule::query()->create([
            'channel' => 'car-gurus',
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'cap_id',
                        'operator' => '=',
                        'value' => '12345'
                    ],
                ],
            ],
        ]);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.sales-channels.update', 'car-gurus'), [
                'conditions' => [],
            ]);

        $response->assertStatus(200);

        $this->assertCount(1, SalesChannelRule::all());
        $this->assertCount(1, SalesChannelRule::query()->where('channel', '=', 'car-gurus')->get());

        $conditions = SalesChannelRule::query()->where('channel', '=', 'car-gurus')->first()?->conditions;

        $this->assertCount(0, $conditions);
    }

    public function testConditionValueArrays()
    {
        $this->setCarWowCarGuruExportSettings();

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.sales-channels.update', 'car-gurus'), [
                'conditions' => [
                    [
                        'value' => [
                            'type' => 'and',
                            'column' => 'cap_id',
                            'operator' => 'in',
                            'value' => '123,456'
                        ],
                    ],
                ],
            ]);

        $response->assertStatus(200);

        $this->assertCount(1, SalesChannelRule::all());
        $this->assertCount(1, SalesChannelRule::query()->where('channel', '=', 'car-gurus')->get());

        $conditions = SalesChannelRule::query()->where('channel', '=', 'car-gurus')->first()?->conditions;

        $this->assertEquals('cap_id', $conditions[0]['value']['column']);
        $this->assertIsArray($conditions[0]['value']['value']);
        $this->assertCount(2, $conditions[0]['value']['value']);
        $this->assertContains('123', $conditions[0]['value']['value']);
        $this->assertContains('456', $conditions[0]['value']['value']);
    }

    private function setCarWowCarGuruExportSettings()
    {
        Event::fake();

        $this->seed(CarWowExportSeeder::class);
        $this->seed(CarGuruExportSeeder::class);

        Settings::update('sales-channels-car-wow-enabled', true);
        Settings::update('sales-channels-car-gurus-enabled', true);

        Event::assertDispatchedTimes(SettingUpdated::class, 2);
    }
}
