<?php

namespace Tests\Tenant;

use App\Jobs\ImportConfiguratorImages;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Str;
use Mtc\MercuryDataModels\CarConfiguratorExtra;
use Mtc\MercuryDataModels\CarConfiguratorModel;
use Mtc\MercuryDataModels\CarConfiguratorPackage;
use Mtc\MercuryDataModels\CarConfiguratorTrim;
use Mtc\MercuryDataModels\Media;
use Mtc\MercuryDataModels\VehicleMake;
use Mtc\MercuryDataModels\VehicleModel;
use Tests\TenantTestCase;
use Tests\UserForTenant;

class CarConfiguratorControllerTest extends TenantTestCase
{
    use UserForTenant;

    /**
    * A basic feature test example.
    *
    * @return void
    */
    public function testIndex()
    {
        CarConfiguratorModel::factory(3)->create(['name' => 'foo faz']);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.car-configurator.search'), [
                'term' => 'foo',
                'selections' => [],
            ]);

        $response->assertStatus(200);
        $this->assertIsArray($response->json('data'));
        $this->assertCount(3, $response->json('data'));
    }

    public function testStore()
    {
        $make = VehicleMake::factory()->create();
        $model = VehicleModel::factory()->create();
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.car-configurator.store'), [
                'name' => 'foo',
                'make_id' => $make->id,
                'model_id' => $model->id,
            ]);

        $response->assertStatus(200);
        $this->assertEquals('foo', $response->json('name'));
        $this->assertTrue(CarConfiguratorModel::query()->where('name', 'foo')->exists());
    }

    public function testUpdate()
    {
        $model = CarConfiguratorModel::factory()->create(['name' => 'foo']);
        $update_trim = CarConfiguratorTrim::factory()->create(['model_id' => $model->id]);
        CarConfiguratorTrim::factory()->create(['model_id' => $model->id]);
        $package = CarConfiguratorPackage::factory()->create();
        $extra = CarConfiguratorExtra::factory()->create();

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.car-configurator.update', $model->id), [
                'name' => 'baz',
                'active' => true,
                'trims' => [
                    [
                        'id' => $update_trim->id,
                        'name' => 'baz',
                        'description' => 'biz ipsum',
                        'price' => 22222,
                    ],
                    [
                        'id' => Str::random(12),
                        'name' => 'faz',
                        'description' => 'lorem ipsum',
                        'price' => 12345,
                    ],
                ],
                'engines' => [
                    [
                        'id' => Str::random(12),
                        'name' => 'faz',
                    ],
                ],
                'wheels' => [
                    [
                        'id' => Str::random(12),
                        'name' => 'faz',
                    ],
                ],
                'interiors' => [
                    [
                        'id' => Str::random(12),
                        'name' => 'faz',
                    ],
                ],
                'packages' => [$package->id],
                'extras' => [$extra->id],
            ]);

        $model->refresh();
        $response->assertStatus(200);
        $this->assertEquals('baz', $model->name);
        $this->assertTrue($model->active);
        $this->assertEquals(2, $model->trims()->count());
        $trim = $model->trims()->orderBy('order')->first();
        $this->assertEquals('baz', $trim->name);
        $this->assertEquals('biz ipsum', $trim->description);
        $this->assertEquals(22222, $trim->price);
    }

    public function testShow()
    {
        $model = CarConfiguratorModel::factory()->create(['name' => 'foo']);

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

        $response->assertStatus(200);
        $this->assertEquals($model->id, $response->json('configurator.id'));
        $this->assertEquals('foo', $response->json('configurator.name'));
        $this->assertArrayHasKey('makes', $response->json());
        $this->assertArrayHasKey('models', $response->json());
        $this->assertArrayHasKey('packages', $response->json());
        $this->assertArrayHasKey('extras', $response->json());
        $this->assertArrayHasKey('fuel_types', $response->json());
        $this->assertArrayHasKey('drivetrains', $response->json());
        $this->assertArrayHasKey('transmissions', $response->json());
    }

    public function testDelete()
    {
        $model = CarConfiguratorModel::factory()->create(['name' => 'foo']);
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->deleteJson(route('tenant.car-configurator.destroy', $model->id));

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

    public function testSaveAndGetMedia()
    {
        Queue::fake();
        $model = CarConfiguratorModel::factory()->create(['name' => 'foo']);
        $media = Media::factory(5)->create();

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.car-configurator.save-media', $model->id), [
                'tags' => [
                    'faz',
                ],
                'media' => $media->pluck('id'),
            ]);

        $response->assertStatus(200);
        $this->assertEquals(5, $model->mediaUses()->count());

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.car-configurator.get-media', $model->id), [
                'tags' => [
                    'faz',
                ],
            ]);

        $response->assertStatus(200);
        $this->assertArrayHasKey('media', $response->json());
        $this->assertArrayHasKey('media_uses', $response->json());
        $this->assertEquals($media->pluck('id')->toArray(), $response->json('media'));
    }


    public function testImportMedia()
    {
        Queue::fake();
        $model = CarConfiguratorModel::factory()->create(['name' => 'foo']);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.car-configurator.import-media', $model->id), [
                'file' => UploadedFile::fake()
                    ->createWithContent('configurator-image-import.json', File::get(dirname(__DIR__) . '/data/configurator-image-import.json')),
            ]);
        $response->assertStatus(200);
        Queue::assertPushed(ImportConfiguratorImages::class);
    }
}
