<?php

namespace Tests\Unit;

use App\Models\ImportCondition;
use App\Traits\ImportChecksConditions;
use Illuminate\Support\Facades\Queue;
use Mtc\ContentManager\Models\Media;
use Mtc\MercuryDataModels\Vehicle;
use Tests\TenantTestCase;

class VehicleImportConditionTest extends TenantTestCase
{
    use ImportChecksConditions;

    public function testNoImportConditions()
    {
        $vehicle = Vehicle::factory()->create(['is_published' => true]);
        $vehicle2 = Vehicle::factory()->create(['is_published' => false]);

        $this->assertTrue($this->shouldBePublished(fn() => $vehicle->is_published, 'test', $vehicle));
        $this->assertFalse($this->shouldBePublished(fn() => $vehicle2->is_published, 'test', $vehicle2));
    }

    public function testImportConditionNoRules()
    {
        $vehicle = Vehicle::factory()->create(['is_published' => true]);
        $vehicle2 = Vehicle::factory()->create(['is_published' => false]);
        ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);

        $this->assertFalse($this->shouldBePublished(fn() => $vehicle->is_published, 'test', $vehicle));
        $this->assertFalse($this->shouldBePublished(fn() => $vehicle2->is_published, 'test', $vehicle2));
    }

    public function testImportConditionSingleRule()
    {
        $vehicle = Vehicle::factory()->create(['make_id' => 1]);
        $vehicle2 = Vehicle::factory()->create(['make_id' => 2]);
        $condition = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition->rules()->create([
            'field' => 'make_id',
            'condition' => '=',
            'value' => 2
        ]);

        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle));
        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle2));
    }
    public function testImportConditionMultipleRule()
    {
        $vehicle = Vehicle::factory()->create(['make_id' => 1, 'fuel_type_id' => 3]);
        $vehicle2 = Vehicle::factory()->create(['make_id' => 1, 'fuel_type_id' => 1]);
        $vehicle3 = Vehicle::factory()->create(['make_id' => 2, 'fuel_type_id' => 3]);
        $vehicle4 = Vehicle::factory()->create(['make_id' => 3, 'fuel_type_id' => 1]);
        $condition = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition->rules()->create([
            'field' => 'make_id',
            'condition' => '=',
            'value' => 2
        ]);

        $condition->rules()->create([
            'field' => 'fuel_type_id',
            'condition' => '=',
            'value' => 3
        ]);

        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle));
        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle2));
        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle3));
        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle4));
    }

    public function testMultipleImportConditionsWithOneMatch()
    {
        $vehicle = Vehicle::factory()->create(['make_id' => 1, 'fuel_type_id' => 3]);
        $vehicle2 = Vehicle::factory()->create(['make_id' => 1, 'fuel_type_id' => 1]);

        $condition = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition->rules()->create([
            'field' => 'make_id',
            'condition' => '=',
            'value' => 2
        ]);
        $condition2 = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition2->rules()->create([
            'field' => 'fuel_type_id',
            'condition' => '=',
            'value' => 3
        ]);

        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle));
        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle2));
    }

    public function testMultipleImportConditionsAllMatch()
    {
        $vehicle = Vehicle::factory()->create(['make_id' => 1, 'fuel_type_id' => 3]);
        $vehicle2 = Vehicle::factory()->create(['make_id' => 1, 'fuel_type_id' => 1]);

        $condition = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition->rules()->create([
            'field' => 'make_id',
            'condition' => '=',
            'value' => 1
        ]);
        $condition2 = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition2->rules()->create([
            'field' => 'fuel_type_id',
            'condition' => '=',
            'value' => 3
        ]);

        $this->assertFalse($this->shouldBePublished(fn() => $vehicle->is_published, 'test', $vehicle));
        $this->assertFalse($this->shouldBePublished(fn() => $vehicle2->is_published, 'test', $vehicle2));
    }

    public function testNotEquals()
    {
        $vehicle = Vehicle::factory()->create(['make_id' => 1]);
        $vehicle2 = Vehicle::factory()->create(['make_id' => 2]);
        $condition = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition->rules()->create([
            'field' => 'make_id',
            'condition' => '!=',
            'value' => 2
        ]);

        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle));
        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle2));
    }

    public function testGreaterThan()
    {
        $vehicle = Vehicle::factory()->create(['price' => 10000]);
        $vehicle2 = Vehicle::factory()->create(['price' => 12000]);
        $vehicle3 = Vehicle::factory()->create(['price' => 9000]);
        $condition = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition->rules()->create([
            'field' => 'price',
            'condition' => '>',
            'value' => 10000
        ]);

        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle));
        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle2));
        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle3));
    }

    public function testGreaterThanEquals()
    {
        $vehicle = Vehicle::factory()->create(['price' => 10000]);
        $vehicle2 = Vehicle::factory()->create(['price' => 12000]);
        $vehicle3 = Vehicle::factory()->create(['price' => 9000]);
        $condition = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition->rules()->create([
            'field' => 'price',
            'condition' => '>=',
            'value' => 10000
        ]);

        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle));
        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle2));
        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle3));
    }

    public function testLessThan()
    {
        $vehicle = Vehicle::factory()->create(['price' => 10000]);
        $vehicle2 = Vehicle::factory()->create(['price' => 12000]);
        $vehicle3 = Vehicle::factory()->create(['price' => 9000]);
        $condition = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition->rules()->create([
            'field' => 'price',
            'condition' => '<',
            'value' => 10000
        ]);

        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle));
        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle2));
        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle3));
    }

    public function testLessThanEquals()
    {
        $vehicle = Vehicle::factory()->create(['price' => 10000]);
        $vehicle2 = Vehicle::factory()->create(['price' => 12000]);
        $vehicle3 = Vehicle::factory()->create(['price' => 9000]);
        $condition = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition->rules()->create([
            'field' => 'price',
            'condition' => '<=',
            'value' => 10000
        ]);

        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle));
        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle2));
        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle3));
    }

    public function testEmpty()
    {
        $vehicle = Vehicle::factory()->create(['make_id' => null]);
        $vehicle2 = Vehicle::factory()->create(['make_id' => 1]);
        $vehicle3 = Vehicle::factory()->create(['make_id' => 2]);
        $condition = ImportCondition::query()->create([
            'provider' => 'test',
            'active' => true,
            'do_not_publish' => true,
        ]);
        $condition->rules()->create([
            'field' => 'make_id',
            'condition' => 'is_null',
            'value' => '',
        ]);

        $this->assertFalse($this->shouldBePublished(fn() => true, 'test', $vehicle));
        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle2));
        $this->assertTrue($this->shouldBePublished(fn() => true, 'test', $vehicle3));
    }

    public function testImageChecksumMatch()
    {
        Queue::fake();
        $m1 = Media::factory()->create(['source_filename' => 'foo.jpg']);
        $m2 = Media::factory()->create(['source_filename' => 'faz.jpg']);
        $m3 = Media::factory()->create(['source_filename' => 'baz.jpg']);
        $cheksum = dechex(crc32(json_encode([3, 'foo.jpg', 'faz.jpg', 'baz.jpg'])));
        $v1 = Vehicle::factory()->create();
        $v2 = Vehicle::factory()->create(['image_checksum' => 'foo']);
        $v3 = Vehicle::factory()->create(['image_checksum' => $cheksum]);

        $images = ['foo.jpg', 'faz.jpg', 'baz.jpg'];
        $this->assertTrue($this->imageChecksumMismatch($images, $v1));
        $this->assertTrue($this->imageChecksumMismatch($images, $v2));
        $this->assertFalse($this->imageChecksumMismatch($images, $v3));

        \Mtc\ContentManager\Facades\Media::setUsesForModel([$m1->id, $m2->id, $m3->id], $v1);
        $this->assertFalse($this->imageChecksumMismatch($images, $v1));

        $images = ['foo.jpg', 'faz.jpg', 'baz.jpg', 'bar.jpg'];
        $this->assertTrue($this->imageChecksumMismatch($images, $v2));
        $this->assertTrue($this->imageChecksumMismatch($images, $v3));
        $images = ['foo.jpg', 'faz.jpg', 'bar.jpg'];
        $this->assertTrue($this->imageChecksumMismatch($images, $v2));
        $this->assertTrue($this->imageChecksumMismatch($images, $v3));
    }
}
