<?php

namespace Tests\Feature;

use App\Exports\AaCarsExport;
use App\Exports\AutoTraderCSVExport;
use App\Exports\AutowebExport;
use App\Exports\CarGurusExport;
use App\Exports\CarsIrelandExport;
use App\Exports\CarSnipExport;
use App\Exports\CarWowExport;
use App\Exports\CarzoneExport;
use App\Exports\ChannelFeedExport;
use App\Exports\EbayMotorsExport;
use App\Exports\HeyCarExport;
use App\Exports\InventoryExport;
use App\Exports\MotoNovoExport;
use App\Exports\MotorsCoUkExport;
use App\Exports\PhyronExport;
use App\Exports\SilverBulletExport;
use App\SalesChannelType;
use Mtc\MercuryDataModels\SalesChannelRule;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleAttribute;
use Mtc\MercuryDataModels\VehicleMake;
use Tests\DatabaseTestCase;
use Tests\UserForTenant;
use App\Facades\Settings;

class SalesChannelTest extends DatabaseTestCase
{
    use UserForTenant;

    public function testSalesChannelNoRules()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'max saving',
            'config_key' => 'sales-channels-ebay-motors-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'is_new' => false,
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'is_new' => true,
        ]);

        $this->assertCount(8, new EbayMotorsExport()->collection());
    }

    public function testSalesChannelRules()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'max saving',
            'config_key' => 'sales-channels-ebay-motors-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'is_new' => false,
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'is_new' => true,
        ]);

        SalesChannelRule::query()->create([
            'channel' => 'ebay-motors',
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'is_new',
                        'operator' => '=',
                        'value' => 0
                    ],
                ],
            ]
        ]);

        $this->assertCount(5, new EbayMotorsExport()->collection());
    }

    public function testMultipleSalesChannelRules()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'max saving',
            'config_key' => 'sales-channels-ebay-motors-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        $vehicle_make_one = VehicleMake::factory()->create([
            'name' => 'foo',
        ]);
        $vehicle_make_two = VehicleMake::factory()->create([
            'name' => 'baz',
        ]);

        Vehicle::factory(7)->create([
            'is_published' => true,
            'is_new' => true,
            'make_id' => $vehicle_make_one->id,
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'is_new' => false,
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'is_new' => true,
            'make_id' => $vehicle_make_two->id,
        ]);

        SalesChannelRule::query()->create([
            'channel' => 'ebay-motors',
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'is_new',
                        'operator' => '=',
                        'value' => true
                    ],
                ],
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'make.name',
                        'operator' => '=',
                        'value' => 'foo'
                    ],
                ],
            ]
        ]);

        $this->assertCount(7, new EbayMotorsExport()->collection());
    }

    public function testSalesChannelNoRulesForChannel()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'max saving',
            'config_key' => 'sales-channels-ebay-motors-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'is_new' => false,
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'is_new' => true,
        ]);

        SalesChannelRule::query()->create([
            'channel' => 'foo',
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'is_new',
                        'operator' => '=',
                        'value' => false
                    ],
                ],
            ]
        ]);

        $this->assertCount(8, new EbayMotorsExport()->collection());
    }

    public function testSalesChannels()
    {
        $this->enableSalesChannelSettings();

        Vehicle::factory(5)->create([
            'is_published' => true,
            'is_new' => false,
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'is_new' => true,
        ]);

        $channels = [
            SalesChannelType::AA_CARS,
            SalesChannelType::AUTOTRADER,
            SalesChannelType::AUTOWEB,
            SalesChannelType::CAR_GURUS,
            SalesChannelType::CARS_IRELAND,
            SalesChannelType::CAR_SNIP,
            SalesChannelType::CAR_WOW,
            SalesChannelType::CARZONE,
            SalesChannelType::CHANNEL_FEED,
            SalesChannelType::EBAY_MOTORS,
            SalesChannelType::HEY_CAR,
            SalesChannelType::INVENTORY,
            SalesChannelType::MOTO_NOVO,
            SalesChannelType::MOTORS_CO_UK,
            SalesChannelType::PHYRON,
            SalesChannelType::SILVER_BULLET,
        ];

        // create rules for each export channel
        collect($channels)->each(
            fn ($channel) => SalesChannelRule::query()->create([
            'channel' => $channel,
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'is_new',
                        'operator' => '=',
                        'value' => false
                    ],
                ],
            ]
        ])
        );

        // loop over exports, assert that each returns correct count
        $exports = [
            AaCarsExport::class,
            AutoTraderCSVExport::class,
            AutowebExport::class,
            CarGurusExport::class,
            CarsIrelandExport::class,
            CarSnipExport::class,
            CarWowExport::class,
            CarzoneExport::class,
            EbayMotorsExport::class,
            HeyCarExport::class,
            InventoryExport::class,
            MotoNovoExport::class,
            MotorsCoUkExport::class,
            PhyronExport::class,
            SilverBulletExport::class,
        ];

        collect($exports)->each(fn ($export) => $this->assertCount(5, new $export()->collection()));
    }

    public function testChannelFeedExport()
    {
        $this->enableSalesChannelSettings();

        Vehicle::factory(5)->create([
            'is_published' => true,
            'is_new' => false,
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'is_new' => true,
        ]);

        SalesChannelRule::query()->create([
            'channel' => SalesChannelType::CHANNEL_FEED,
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'is_new',
                        'operator' => '=',
                        'value' => false
                    ],
                ],
            ]
        ]);

        // channel feed does not have collection() function so test it separately
        $this->assertCount(5, new ChannelFeedExport()->query()->get());
    }

    public function testInOperatorBoolean()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'max saving',
            'config_key' => 'sales-channels-ebay-motors-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'is_new' => false,
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'is_new' => true,
        ]);

        SalesChannelRule::query()->create([
            'channel' => 'ebay-motors',
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'is_new',
                        'operator' => 'in',
                        'value' => [
                            '0',
                            '1',
                        ]
                    ],
                ],
            ]
        ]);

        $this->assertCount(8, new EbayMotorsExport()->collection());
    }

    public function testInOperatorString()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'max saving',
            'config_key' => 'sales-channels-ebay-motors-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        $make_one = VehicleMake::factory()->create([
            'name' => 'foo',
        ]);

        $make_two = VehicleMake::factory()->create([
            'name' => 'baz',
        ]);

        $make_three = VehicleMake::factory()->create([
            'name' => 'bar',
        ]);

        Vehicle::factory(5)->create([
            'is_published' => true,
            'is_new' => false,
            'make_id' => $make_one,
        ]);

        Vehicle::factory(3)->create([
            'is_published' => true,
            'is_new' => true,
            'make_id' => $make_two,
        ]);

        Vehicle::factory(10)->create([
            'is_published' => true,
            'is_new' => true,
            'make_id' => $make_three,
        ]);

        SalesChannelRule::query()->create([
            'channel' => 'ebay-motors',
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'make.name',
                        'operator' => 'in',
                        'value' => [
                            'foo',
                            'baz',
                        ]
                    ],
                ],
            ]
        ]);

        $this->assertCount(18, Vehicle::all());
        $this->assertCount(8, new EbayMotorsExport()->collection());
    }

    public function testSalesChannelBooleanAttributeRule()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'max saving',
            'config_key' => 'sales-channels-ebay-motors-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        $attribute = VehicleAttribute::factory()->create([
            'model' => 'vehicle',
            'name' => 'Pull to AT Connect',
            'slug' => 'pull-to-at-connect',
            'type' => 'boolean',
        ]);

        $included = Vehicle::factory(3)->create(['is_published' => true]);
        $excluded = Vehicle::factory(2)->create(['is_published' => true]);

        $included->each(fn (Vehicle $vehicle) => $vehicle->attributeValues()->create([
            'attribute_id' => $attribute->id,
            'slug' => 'pull-to-at-connect',
            'type' => 'boolean',
            'value_integer' => 1,
        ]));
        $excluded->each(fn (Vehicle $vehicle) => $vehicle->attributeValues()->create([
            'attribute_id' => $attribute->id,
            'slug' => 'pull-to-at-connect',
            'type' => 'boolean',
            'value_integer' => 0,
        ]));

        SalesChannelRule::query()->create([
            'channel' => 'ebay-motors',
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'attribute.pull-to-at-connect',
                        'operator' => '=',
                        'value' => 'yes',
                    ],
                ],
            ],
        ]);

        $this->assertCount(3, new EbayMotorsExport()->collection());
    }

    public function testSalesChannelTextAttributeRule()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'max saving',
            'config_key' => 'sales-channels-ebay-motors-enabled',
            'value' => true,
            'type' => 'boolean',
        ]);

        $attribute = VehicleAttribute::factory()->create([
            'model' => 'vehicle',
            'name' => 'Connect Status',
            'slug' => 'connect-status',
            'type' => 'text',
        ]);

        $approved = Vehicle::factory(4)->create(['is_published' => true]);
        $rejected = Vehicle::factory(3)->create(['is_published' => true]);

        $approved->each(fn (Vehicle $vehicle) => $vehicle->attributeValues()->create([
            'attribute_id' => $attribute->id,
            'slug' => 'connect-status',
            'type' => 'text',
            'value_text' => 'approved',
        ]));
        $rejected->each(fn (Vehicle $vehicle) => $vehicle->attributeValues()->create([
            'attribute_id' => $attribute->id,
            'slug' => 'connect-status',
            'type' => 'text',
            'value_text' => 'rejected',
        ]));

        SalesChannelRule::query()->create([
            'channel' => 'ebay-motors',
            'conditions' => [
                [
                    'value' => [
                        'type' => 'and',
                        'column' => 'attribute.connect-status',
                        'operator' => '=',
                        'value' => 'approved',
                    ],
                ],
            ],
        ]);

        $this->assertCount(4, new EbayMotorsExport()->collection());
    }

    private function enableSalesChannelSettings()
    {
        $channel_setting_keys = collect([
            'sales-channels-aa-cars-enabled',
            'sales-channels-autoweb-enabled',
            'sales-channels-car-gurus-enabled',
            'sales-channels-car-wow-enabled',
            'sales-channels-cars-ireland-enabled',
            'sales-channels-car-snip-enabled',
            'sales-channels-carzone-enabled',
            'sales-channels-channel-feed-enabled',
            'sales-channels-ebay-motors-enabled',
            'sales-channels-hey-car-enabled',
            'sales-channels-inventory-enabled',
            'sales-channels-moto-novo-enabled',
            'sales-channels-motors-co-uk-enabled',
            'sales-channels-phyron-enabled',

        ]);

        $channel_setting_keys->each(fn ($key) => Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'channel setting',
            'config_key' => $key,
            'value' => true,
            'type' => 'boolean',
        ]));
    }
}
