<?php

namespace Tests\Feature\Controllers;

use App\Models\ExportMapTemplate;
use Tests\DatabaseTestCase;
use Tests\UserForTenant;

class ExportMapTemplateControllerTest extends DatabaseTestCase
{
    use UserForTenant;

    /**
     * Test fetching a paginated list of export map templates.
     *
     * @return void
     */
    public function testIndex()
    {
        // Create 3 templates to ensure pagination works
        ExportMapTemplate::factory(3)->create();

        $response = $this->actingAs($this->getUser())
            ->getJson(route('export-map-templates.index', [], false));

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

    /**
     * Test creating a new export map template.
     *
     * @return void
     */
    public function testStore()
    {
        $postData = [
            'title' => 'My New Custom Template'
        ];

        $response = $this->actingAs($this->getUser())
            ->postJson(route('export-map-templates.store', [], false), $postData);

        $response->assertStatus(201);
        $this->assertEquals($postData['title'], $response->json('title'));

        // Verify it was created in the database
        $this->assertTrue(ExportMapTemplate::query()->where('title', $postData['title'])->exists());

        // The controller should create it as not published by default
        $template = ExportMapTemplate::query()->where('title', $postData['title'])->first();
        $this->assertFalse($template->is_published);
    }

    /**
     * Test updating an existing export map template.
     *
     * @return void
     */
    public function testUpdate()
    {
        $template = ExportMapTemplate::factory()->create(['title' => 'Old Title']);

        $updateData = [
            'is_published' => true,
            'sales_channel' => 'test-channel',
            'title' => 'Updated Template Title',
            'type' => 'vehicle',
            'columns' => [
                "uuid",
                "vin",
                "model.name",
            ],
            'headers' => [
                "Vehicle_ID",
                "VIN",
                "ModelRange",
            ],
            'mapping_rules' => [
                [
                    "when" => [
                        "field" => "type",
                        "op" => "eq",
                        "value" => "car"
                    ],
                    "then" => [
                        [
                            "action" => "set",
                            "target" => "type",
                            "value" => "Passenger Vehicle"
                        ]
                    ]
                ]
            ],
        ];

        $response = $this->actingAs($this->getUser())
            ->putJson(route('export-map-templates.update', $template->id, false), $updateData);

        $response->assertStatus(200);

        // Refresh the model from the database to check updated values
        $template->refresh();

        $this->assertEquals($updateData['title'], $template->title);
        $this->assertEquals($updateData['sales_channel'], $template->sales_channel);
        $this->assertEquals($updateData['columns'], $template->columns);
        $this->assertEquals($updateData['mapping_rules'], $template->mapping_rules);
        $this->assertTrue($template->is_published);
    }

    /**
     * Test fetching a single export map template.
     *
     * @return void
     */
    public function testShow()
    {
        $template = ExportMapTemplate::factory()->create(['title' => 'Show Me']);

        $response = $this->actingAs($this->getUser())
            ->getJson(route('export-map-templates.show', $template->id, false));

        $response->assertStatus(200);
        $this->assertEquals($template->id, $response->json('id'));
        $this->assertEquals('Show Me', $response->json('title'));
    }

    /**
     * Test deleting an export map template.
     *
     * @return void
     */
    public function testDelete()
    {
        $template = ExportMapTemplate::factory()->create();

        $response = $this->actingAs($this->getUser())
            ->deleteJson(route('export-map-templates.destroy', $template->id, false));

        // The destroy method in the controller returns the index, so status is 200
        $response->assertStatus(200);

        // Assert the model no longer exists in the database
        $this->assertFalse(ExportMapTemplate::query()->where('id', $template->id)->exists());
    }

    public function testStoreCreatesOfferTemplate()
    {
        $postData = [
            'title' => 'Offer Template',
            'type' => 'offer',
        ];

        $response = $this->actingAs($this->getUser())
            ->postJson(route('export-map-templates.store', [], false), $postData);

        $response->assertStatus(201);
        $this->assertEquals('offer', $response->json('type'));

        $template = ExportMapTemplate::query()->where('title', $postData['title'])->first();
        $this->assertEquals('offer', $template->type);
    }

    public function testShowReturnsOfferFieldsForOfferType()
    {
        $template = ExportMapTemplate::factory()->create([
            'title' => 'Offer Fields Test',
            'type' => 'offer',
        ]);

        $response = $this->actingAs($this->getUser())
            ->getJson(route('export-map-templates.show', $template->id, false));

        $response->assertStatus(200);

        $availableFieldIds = collect($response->json('data_options.available_fields'))->pluck('id')->all();
        $this->assertContains('offerType.name', $availableFieldIds);
        $this->assertContains('full_price', $availableFieldIds);
    }

    public function testUpdateOfferTemplate()
    {
        $template = ExportMapTemplate::factory()->create([
            'title' => 'Old Offer',
            'type' => 'offer',
        ]);

        $updateData = [
            'is_published' => true,
            'title' => 'Updated Offer Template',
            'type' => 'offer',
            'columns' => ['name', 'price', 'offerType.name'],
            'headers' => ['Name', 'Price', 'Offer Type'],
        ];

        $response = $this->actingAs($this->getUser())
            ->putJson(route('export-map-templates.update', $template->id, false), $updateData);

        $response->assertStatus(200);

        $template->refresh();
        $this->assertEquals('offer', $template->type);
        $this->assertEquals($updateData['columns'], $template->columns);
    }

    public function testStoreCreatesDealershipTemplate()
    {
        $postData = [
            'title' => 'Dealership Template',
            'type' => 'dealership',
        ];

        $response = $this->actingAs($this->getUser())
            ->postJson(route('export-map-templates.store', [], false), $postData);

        $response->assertStatus(201);
        $this->assertEquals('dealership', $response->json('type'));

        $template = ExportMapTemplate::query()->where('title', $postData['title'])->first();
        $this->assertEquals('dealership', $template->type);
    }

    public function testShowReturnsDealershipFieldsForDealershipType()
    {
        $template = ExportMapTemplate::factory()->create([
            'title' => 'Dealership Fields Test',
            'type' => 'dealership',
        ]);

        $response = $this->actingAs($this->getUser())
            ->getJson(route('export-map-templates.show', $template->id, false));

        $response->assertStatus(200);

        $availableFieldIds = collect($response->json('data_options.available_fields'))->pluck('id')->all();
        $this->assertContains('name', $availableFieldIds);
        $this->assertContains('postcode', $availableFieldIds);
        $this->assertContains('franchise.name', $availableFieldIds);
    }

    public function testUpdateDealershipTemplate()
    {
        $template = ExportMapTemplate::factory()->create([
            'title' => 'Old Dealership',
            'type' => 'dealership',
        ]);

        $updateData = [
            'is_published' => true,
            'title' => 'Updated Dealership Template',
            'type' => 'dealership',
            'columns' => ['name', 'email', 'postcode'],
            'headers' => ['Name', 'Email', 'Postcode'],
        ];

        $response = $this->actingAs($this->getUser())
            ->putJson(route('export-map-templates.update', $template->id, false), $updateData);

        $response->assertStatus(200);

        $template->refresh();
        $this->assertEquals('dealership', $template->type);
        $this->assertEquals($updateData['columns'], $template->columns);
    }
}
