<?php

namespace Tests\Tenant;

use App\Console\Commands\ClearAudit;
use App\Console\Commands\ExceptionReportingTest;
use App\Console\Commands\ExportToSilverBullet;
use App\Console\Commands\FixSpecDataMorphType;
use App\Console\Commands\RemoveArchivedVehicles;
use App\Console\Commands\SetMissingVehicleTitles;
use App\Facades\Settings;
use App\Jobs\RunSilverBulletExport;
use App\Traits\TrackedSeeding;
use Carbon\Carbon;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Queue;
use Mtc\MercuryDataModels\Audit;
use Mtc\MercuryDataModels\ReportingStat;
use Mtc\MercuryDataModels\SalesChannelHistory;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleFeature;
use Mtc\MercuryDataModels\VehicleStandardEquipment;
use Mtc\MercuryDataModels\VehicleTechnicalData;
use Tests\TenantTestCase;
use Tests\UserForTenant;

class CommandTestForTenant extends TenantTestCase
{
    use UserForTenant;
    use TrackedSeeding;

    public function testClearStats()
    {
        Config::set('automotive.dashboard-history-length', 10);
        ReportingStat::factory()->create(['date' => Carbon::now()->subDays(20)]);
        ReportingStat::factory()->create(['date' => Carbon::now()]);

        $this->assertEquals(2, ReportingStat::query()->count());
        $this->artisan('clear:stats')->assertExitCode(0);
        $this->assertEquals(1, ReportingStat::query()->count());
    }

    public function testClearSalesChannelHistory()
    {
        Config::set('logging.sales-channel-history-age', 10);
        SalesChannelHistory::factory()->create(['created_at' => Carbon::now()->subDays(20)]);
        SalesChannelHistory::factory()->create(['created_at' => Carbon::now()]);

        $this->assertEquals(2, SalesChannelHistory::query()->count());
        $this->artisan('clear:sales-channel-history')->assertExitCode(0);
        $this->assertEquals(1, SalesChannelHistory::query()->count());
    }

    public function testCleanAudit()
    {
        Audit::query()->create([
            'user_type' => 'user',
            'user_id' => $this->getUser()->id,
            'auditable_type' => 'foo',
            'auditable_id' => 1,
            'old_values' => '[]',
            'new_values' => '[]',
            'event' => 'updated',
            'url' => 'foo.com',
            'ip_address' => '1.1.1.1',
            'user_agent' => 'abc',
            'created_at' => Carbon::now()->subYears(2),
        ]);
        Audit::query()->create([
            'user_type' => 'user',
            'user_id' => $this->getUser()->id,
            'auditable_type' => 'foo',
            'auditable_id' => 1,
            'event' => 'updated',
            'old_values' => '[]',
            'new_values' => '[]',
            'url' => 'foo.com',
            'ip_address' => '1.1.1.1',
            'user_agent' => 'abc',
            'created_at' => Carbon::now(),
        ]);
        $this->artisan(ClearAudit::class)->assertExitCode(0);
        $this->assertEquals(1, Audit::query()->count());
    }

    public function testExceptionThrowing()
    {
        $this->expectException(\Exception::class);
        $this->artisan(ExceptionReportingTest::class);
    }

    public function testFixSpecDataMorphType()
    {
        VehicleFeature::factory()->create(['vehicle_type' => null]);
        VehicleTechnicalData::factory()->create(['vehicle_type' => null]);
        VehicleStandardEquipment::factory()->create(['vehicle_type' => null]);
        $this->artisan(FixSpecDataMorphType::class)->assertExitCode(0);


        $this->assertFalse(VehicleFeature::query()->where(['vehicle_type' => null])->exists());
        $this->assertFalse(VehicleTechnicalData::query()->where(['vehicle_type' => null])->exists());
        $this->assertFalse(VehicleStandardEquipment::query()->where(['vehicle_type' => null])->exists());
    }

    public function testExportToSilverBullet()
    {
        Queue::fake();
        $this->artisan(ExportToSilverBullet::class)->assertExitCode(0);
        Queue::assertPushed(RunSilverBulletExport::class);
    }

    public function testPurgeVehicles()
    {
        tenant()->live_at = Carbon::now();
        Vehicle::factory(5)->create(['deleted_at' => Carbon::now()->subMonths(6), 'purged_at' => null]);
        Vehicle::factory(4)->create(['deleted_at' => Carbon::now()->subWeek(), 'purged_at' => null]);
        Vehicle::factory(2)->create();
        Vehicle::factory(3)->create(['deleted_at' => Carbon::now()->subYears(3), 'purged_at' => null]);
        $this->artisan(RemoveArchivedVehicles::class)->assertExitCode(0);
        $this->assertEquals(11, Vehicle::withTrashed()->count());
        $this->assertEquals(5, Vehicle::onlyTrashed()->whereNotNull('purged_at')->count());
        $this->assertEquals(4, Vehicle::onlyTrashed()->whereNull('purged_at')->count());
        $this->assertEquals(
            0,
            Vehicle::onlyTrashed()
            ->where('deleted_at', '<=', Carbon::now()->subYears(3))
            ->count()
        );
        $this->assertEquals(2, Vehicle::query()->count());
    }

    public function testSetMissingVehicleTitlesDisabled()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'General',
            'group' => 'Vehicles',
            'name' => 'Automatically set vehicle title from make and model',
            'config_key' => 'auto-update-vehicle-title',
            'type' => 'boolean',
            'value' => false,
        ]);

        Vehicle::factory()->create([
            'title' => null,
        ]);

        $this->artisan(SetMissingVehicleTitles::class)->assertExitCode(0);

        // assert that we didn't set the title
        $this->assertCount(1, Vehicle::query()->whereNull('title')->get());
    }

    public function testSetMissingVehicleTitlesNoEligibleVehicles()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'General',
            'group' => 'Vehicles',
            'name' => 'Automatically set vehicle title from make and model',
            'config_key' => 'auto-update-vehicle-title',
            'type' => 'boolean',
            'value' => false,
        ]);

        Vehicle::factory()->create([
            'title' => null,
            'make_id' => null,
            'model_id' => null,
        ]);

        Settings::update('auto-update-vehicle-title', true);

        $this->artisan(SetMissingVehicleTitles::class)->assertExitCode(0);

        // assert that we didn't set the title
        $this->assertCount(1, Vehicle::query()->whereNull('title')->get());
    }

    public function testSetMissingVehicleTitleSet()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'General',
            'group' => 'Vehicles',
            'name' => 'Automatically set vehicle title from make and model',
            'config_key' => 'auto-update-vehicle-title',
            'type' => 'boolean',
            'value' => false,
        ]);

        $make = \Mtc\MercuryDataModels\VehicleMake::factory()->create([
            'name' => 'foo',
        ]);

        $model = \Mtc\MercuryDataModels\VehicleModel::factory()->create([
            'make_id' => $make->id,
            'name' => 'bar',
        ]);

        Vehicle::factory()->create([
            'title' => 'existing title',
            'make_id' => $make->id,
            'model_id' => $model->id,
        ]);

        Settings::update('auto-update-vehicle-title', true);

        $this->artisan(SetMissingVehicleTitles::class)->assertExitCode(0);

        // assert that we didn't overwrite the existing title
        $this->assertCount(1, Vehicle::query()->where('title', 'existing title')->get());
    }

    public function testSetMissingVehicleTitlesWorking()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'General',
            'group' => 'Vehicles',
            'name' => 'Automatically set vehicle title from make and model',
            'config_key' => 'auto-update-vehicle-title',
            'type' => 'boolean',
            'value' => false,
        ]);

        $make = \Mtc\MercuryDataModels\VehicleMake::factory()->create([
            'name' => 'foo',
        ]);

        $model = \Mtc\MercuryDataModels\VehicleModel::factory()->create([
            'make_id' => $make->id,
            'name' => 'bar',
        ]);

        Vehicle::factory()->create([
            'title' => null,
            'make_id' => $make->id,
            'model_id' => $model->id,
        ]);

        Settings::update('auto-update-vehicle-title', true);

        $this->artisan(SetMissingVehicleTitles::class)->assertExitCode(0);

        // assert that we correctly set the title
        $this->assertCount(1, Vehicle::query()->where('title', 'foo bar')->get());
    }

    public function testSetMissingVehicleTitlesChunk()
    {
        Settings::make([
            'tab' => 'Automotive',
            'section' => 'General',
            'group' => 'Vehicles',
            'name' => 'Automatically set vehicle title from make and model',
            'config_key' => 'auto-update-vehicle-title',
            'type' => 'boolean',
            'value' => false,
        ]);

        $make = \Mtc\MercuryDataModels\VehicleMake::factory()->create([
            'name' => 'foo',
        ]);

        $model = \Mtc\MercuryDataModels\VehicleModel::factory()->create([
            'make_id' => $make->id,
            'name' => 'bar',
        ]);

        Vehicle::factory(250)->create([
            'title' => null,
            'make_id' => $make->id,
            'model_id' => $model->id,
        ]);

        Settings::update('auto-update-vehicle-title', true);

        $this->artisan(SetMissingVehicleTitles::class)->assertExitCode(0);

        // assert that we correctly set the title
        $this->assertCount(250, Vehicle::query()->where('title', 'foo bar')->get());
    }
}
