<?php

namespace Tests\Tenant;

use App\Facades\Settings;
use App\Jobs\RunLabelAssignmentForVehiclesJob;
use Illuminate\Support\Facades\Queue;
use Mtc\MercuryDataModels\FuelType;
use Mtc\MercuryDataModels\Label;
use Mtc\MercuryDataModels\LabelRule;
use Mtc\MercuryDataModels\TransmissionType;
use Mtc\MercuryDataModels\Vehicle;
use Mtc\MercuryDataModels\VehicleModel;
use Tests\TenantTestCase;
use Tests\UserForTenant;

class LabelControllerTest extends TenantTestCase
{
    use UserForTenant;

    public function testIndex()
    {
        Label::factory(5)->create();
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson('/api/labels');

        $response->assertStatus(200);
        $this->assertArrayHasKey('data', $response->json());
        $this->assertIsArray($response->json('data'));
        $this->assertCount(5, $response->json('data'));
        $this->assertArrayHasKey('title', $response->json('data.0'));
        $this->assertArrayHasKey('link', $response->json('data.0'));
        $this->assertArrayHasKey('id', $response->json('data.0'));
    }

    public function testShow()
    {
        $label = Label::factory()->create(['name' => 'foo baz bar']);
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.labels.show', $label));

        $response->assertStatus(200);
        $this->assertIsArray($response->json());
        $this->assertEquals('foo baz bar', $response->json('name'));
        $this->assertArrayHasKey('couldAutomate', $response->json());
        $this->assertArrayHasKey('data', $response->json());
        $this->assertArrayHasKey('auto_assign', $response->json('data'));
        $this->assertArrayHasKey('assign_when', $response->json('data'));
        $this->assertArrayHasKey('auto_revoke', $response->json('data'));
        $this->assertArrayHasKey('revoke_when', $response->json('data'));
        $this->assertArrayHasKey('automation_options', $response->json('data'));
    }
    public function testStore()
    {
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.labels.store'), [
                'name' => 'foo baz bar'
            ]);

        $response->assertStatus(201);
        $this->assertEquals('foo baz bar', $response->json('name'));
        $this->assertArrayHasKey('couldAutomate', $response->json());
        $this->assertArrayHasKey('data', $response->json());
    }

    public function testUpdate()
    {
        $label = Label::factory()->create(['name' => 'foo baz bar']);
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.labels.update', $label), [
                'name' => 'lorem ipsum',
                'data' => [
                    'auto_assign' => true,
                    'assign_when' => 'is_new',
                    'rules' => [],
                ]
            ]);

        $response->assertStatus(200);
        $this->assertIsArray($response->json());
        $this->assertEquals('lorem ipsum', $response->json('name'));
        $label->refresh();
        $this->assertTrue($label->data['auto_assign']);
        $this->assertEquals('is_new', $label->data['assign_when']);
    }

    public function testDestroy()
    {
        $label = Label::factory()->create(['name' => 'foo baz bar']);
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->deleteJson(route('tenant.labels.destroy', $label));

        $response->assertStatus(200);
        $this->assertFalse(Label::query()->where('id', $label->id)->exists());
    }

    public function testAssign()
    {
        Queue::fake();
        $label = Label::factory()->create(['name' => 'foo baz bar']);
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.labels.assign', $label));

        $response->assertStatus(200);
        Queue::assertPushed(RunLabelAssignmentForVehiclesJob::class);
    }

    public function testRemove()
    {
        $label = Label::factory()->create(['name' => 'foo baz bar']);
        $vehicles = Vehicle::factory(4)->create();
        $label->vehicles()->attach($vehicles->pluck('id'));
        $this->assertEquals(4, $label->vehicles()->count());
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.labels.remove', $label));

        $response->assertStatus(200);
        $this->assertEquals(0, $label->vehicles()->count());
    }

    public function testSelectOptions()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'advanced labels',
            'config_key' => 'vehicle-labels-advanced-rules-enabled',
            'value' => 'true',
            'type' => 'bool',
        ]);

        FuelType::factory(5)->create();
        TransmissionType::factory(6)->create();
        VehicleModel::factory(7)->create();

        $label = Label::factory()->create(['name' => 'foo baz bar']);
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.labels.show', $label));

        $response->assertStatus(200);
        $this->assertIsArray($response->json());
        $this->assertArrayHasKey('data', $response->json());
        $this->assertArrayHasKey('options', $response->json('data'));

        $this->assertArrayHasKey('vehicle_is_new', $response->json('data.options'));
        $this->assertArrayHasKey('vehicle_type', $response->json('data.options'));
        $this->assertArrayHasKey('transmission_id', $response->json('data.options'));
        $this->assertArrayHasKey('fuel_type_id', $response->json('data.options'));
        $this->assertArrayHasKey('make_ids', $response->json('data.options'));
        $this->assertArrayHasKey('model_ids', $response->json('data.options'));

        $this->assertCount(5, $response->json('data.options.fuel_type_id'));
        $this->assertCount(6, $response->json('data.options.transmission_id'));
        $this->assertCount(7, $response->json('data.options.make_ids'));
        $this->assertCount(7, $response->json('data.options.model_ids'));
    }

    public function testRulesPopulatedForEdit()
    {
        Settings::make([
            'tab' => 'foo-baz',
            'section' => 'lorem',
            'group' => 'ipsum',
            'name' => 'advanced labels',
            'config_key' => 'vehicle-labels-advanced-rules-enabled',
            'value' => 'true',
            'type' => 'bool',
        ]);

        $label = Label::factory()->create(['name' => 'foo baz bar']);

        LabelRule::factory()->create([
            'label_id' => $label->id,
            'condition_field' => 'transmission_id',
            'condition_value' => 123,
        ]);

        LabelRule::factory()->create([
            'label_id' => $label->id,
            'condition_field' => 'fuel_type_id',
            'condition_value' => 456,
        ]);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.labels.show', $label));

        $response->assertStatus(200);
        $this->assertIsArray($response->json());
        $this->assertArrayHasKey('data', $response->json());
        $this->assertArrayHasKey('rules', $response->json()['data']);
        $this->assertCount(27, $response->json()['data']['rules']);
        $this->assertArrayHasKey('fuel_type_id', $response->json()['data']['rules']);
        $this->assertArrayHasKey('transmission_id', $response->json()['data']['rules']);
        $this->assertArrayHasKey('vehicle_price_min', $response->json()['data']['rules']);
        $this->assertArrayHasKey('vrm_is_empty', $response->json()['data']['rules']);
        $this->assertEquals(123, $response->json()['data']['rules']['transmission_id']['condition_value']);
        $this->assertEquals(456, $response->json()['data']['rules']['fuel_type_id']['condition_value']);
        $this->assertEmpty($response->json()['data']['rules']['vehicle_price_min']['condition_value']);
    }
}
