<?php

namespace Tests\Tenant;

use Mtc\MercuryDataModels\VehicleAttribute;
use Tests\TenantTestCase;
use Tests\UserForTenant;

class VehicleAttributeControllerTest extends TenantTestCase
{
    use UserForTenant;

    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function testIndex()
    {
        VehicleAttribute::factory(4)->create(['model' => 'vehicle']);
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.attributes.index', 'vehicle'));

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

    public function testStore()
    {
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.attributes.store', 'vehicle'), [
                'name' => 'foo baz bar',
                'type' => 'number',
                'unit' => 'L',
            ]);

        $response->assertStatus(201);

        $this->assertEquals('foo baz bar', $response->json('attribute.name'));
        $this->assertEquals('L', $response->json('attribute.unit'));
        $this->assertTrue(VehicleAttribute::query()->where('name', 'foo baz bar')->exists());
        $this->assertTrue(VehicleAttribute::query()->where('id', $response->json('attribute.id'))->exists());
    }

    public function testShow()
    {
        $attribute = VehicleAttribute::factory()->create([
            'model' => 'vehicle',
            'name' => 'foo baz bar',
            'type' => 'number',
        ]);
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.attributes.show', ['vehicle', $attribute]));

        $response->assertStatus(200);

        $this->assertEquals('foo baz bar', $response->json('attribute.name'));
        $this->assertEquals('number', $response->json('attribute.type'));
    }

    public function testUpdate()
    {
        $attribute = VehicleAttribute::factory()->create(['model' => 'vehicle']);
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.attributes.update', ['vehicle', $attribute]), [
                'name' => 'lorem ipsum',
                'type' => 'number',
                'count' => 3,
                'unit' => 'kWh',
            ]);

        $response->assertStatus(200);

        $attribute->refresh();
        $this->assertEquals('lorem ipsum', $attribute->name);
        $this->assertEquals('number', $attribute->type);
        $this->assertEquals(3, $attribute->count);
        $this->assertEquals('kWh', $attribute->unit);
    }


    public function testDestroy()
    {
        $attribute = VehicleAttribute::factory()->create(['model' => 'vehicle']);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->deleteJson(route('tenant.attributes.destroy', ['vehicle', $attribute]));

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

    public function testUpdateAllowsChangingSlug()
    {
        $attribute = VehicleAttribute::factory()->create([
            'model' => 'vehicle',
            'name' => 'Promotional Graphic',
            'slug' => 'promotional-graphic',
        ]);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.attributes.update', ['vehicle', $attribute]), [
                'name' => 'Promotional Graphic',
                'slug' => 'promo-graphic',
            ]);

        $response->assertStatus(200);
        $this->assertEquals('promo-graphic', $attribute->fresh()->slug);
    }

    public function testUpdateRejectsInvalidSlugFormat()
    {
        $attribute = VehicleAttribute::factory()->create([
            'model' => 'vehicle',
            'slug' => 'good-slug',
        ]);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.attributes.update', ['vehicle', $attribute]), [
                'slug' => 'Bad Slug!',
            ]);

        $response->assertStatus(422)->assertJsonValidationErrors(['slug']);
        $this->assertEquals('good-slug', $attribute->fresh()->slug);
    }

    public function testUpdateRejectsDuplicateSlugWithinSameModel()
    {
        VehicleAttribute::factory()->create([
            'model' => 'vehicle',
            'slug' => 'taken-slug',
        ]);
        $attribute = VehicleAttribute::factory()->create([
            'model' => 'vehicle',
            'slug' => 'my-slug',
        ]);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.attributes.update', ['vehicle', $attribute]), [
                'slug' => 'taken-slug',
            ]);

        $response->assertStatus(422)->assertJsonValidationErrors(['slug']);
    }

    public function testUpdateAllowsSameSlugWhenScopedToDifferentModel()
    {
        VehicleAttribute::factory()->create([
            'model' => 'offer',
            'slug' => 'shared-slug',
        ]);
        $attribute = VehicleAttribute::factory()->create([
            'model' => 'vehicle',
            'slug' => 'something-else',
        ]);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.attributes.update', ['vehicle', $attribute]), [
                'slug' => 'shared-slug',
            ]);

        $response->assertStatus(200);
        $this->assertEquals('shared-slug', $attribute->fresh()->slug);
    }

    public function testUpdateRegeneratesSlugWhenCleared()
    {
        $attribute = VehicleAttribute::factory()->create([
            'model' => 'vehicle',
            'name' => 'Renamed Attribute',
            'slug' => 'old-slug',
        ]);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.attributes.update', ['vehicle', $attribute]), [
                'name' => 'Renamed Attribute',
                'slug' => '',
            ]);

        $response->assertStatus(200);
        $this->assertEquals('renamed-attribute', $attribute->fresh()->slug);
    }
}
