<?php

namespace Tests\Feature\Controllers;

use App\Models\ExportMap;
use Mtc\MercuryDataModels\SalesChannelHistory;
use Tests\DatabaseTestCase;
use Tests\UserForTenant;

class ExportMapControllerTest extends DatabaseTestCase
{
    use UserForTenant;

    protected function setUp(): void
    {
        parent::setUp();

        $this->withHeader('X-Tenant', tenant('id'));
    }

    public function test_index_returns_paginated_list()
    {
        ExportMap::factory(3)->create();

        $response = $this->actingAs($this->getUser())
            ->getJson('api/settings/export-maps');

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

    public function test_store_creates_vehicle_export_map()
    {
        $response = $this->actingAs($this->getUser())
            ->postJson('api/settings/export-maps', [
                'name' => 'Test Vehicle Map',
                'type' => 'vehicle',
            ]);

        $response->assertStatus(201);
        $this->assertEquals('vehicle', $response->json('type'));
        $this->assertNotEmpty($response->json('uuid'));
    }

    public function test_store_creates_offer_export_map()
    {
        $response = $this->actingAs($this->getUser())
            ->postJson('api/settings/export-maps', [
                'name' => 'Test Offer Map',
                'type' => 'offer',
            ]);

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

    public function test_store_generates_uuid_automatically()
    {
        $response = $this->actingAs($this->getUser())
            ->postJson('api/settings/export-maps', [
                'name' => 'Auto UUID Map',
                'type' => 'vehicle',
            ]);

        $response->assertStatus(201);
        $this->assertNotEmpty($response->json('uuid'));
        $this->assertTrue(
            preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/', $response->json('uuid')) === 1
        );
    }

    public function test_show_returns_data_options_with_available_and_condition_fields()
    {
        $exportMap = ExportMap::factory()->create(['type' => 'vehicle']);

        $response = $this->actingAs($this->getUser())
            ->getJson("api/settings/export-maps/{$exportMap->id}");

        $response->assertStatus(200);
        $this->assertArrayHasKey('available_fields', $response->json('data_options'));
        $this->assertArrayHasKey('condition_fields', $response->json('data_options'));
    }

    public function test_show_returns_offer_specific_fields_for_offer_type()
    {
        $exportMap = ExportMap::factory()->offerType()->create();

        $response = $this->actingAs($this->getUser())
            ->getJson("api/settings/export-maps/{$exportMap->id}");

        $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 test_update_toggles_api_url_enabled_and_returns_api_url()
    {
        $exportMap = ExportMap::factory()->create([
            'type' => 'vehicle',
            'format' => 'csv',
        ]);

        $response = $this->actingAs($this->getUser())
            ->putJson("api/settings/export-maps/{$exportMap->id}", array_merge(
                $exportMap->toArray(),
                [
                    'api_url_enabled' => true,
                    'ftp_export_enabled' => false,
                    'schedule_enabled' => false,
                ]
            ));

        $response->assertStatus(200);
        $this->assertTrue($response->json('api_url_enabled'));
        $this->assertNotEmpty($response->json('api_url'));
        $this->assertStringContainsString($exportMap->fresh()->uuid, $response->json('api_url'));
    }

    public function test_update_persists_ssl_flag_for_ftp_connection()
    {
        $exportMap = ExportMap::factory()->create([
            'type' => 'vehicle',
            'format' => 'csv',
            'ssl' => false,
        ]);

        $response = $this->actingAs($this->getUser())
            ->putJson("api/settings/export-maps/{$exportMap->id}", array_merge(
                $exportMap->toArray(),
                [
                    'ftp_export_enabled' => true,
                    'driver' => 'ftp',
                    'host' => 'ftp.example.test',
                    'root' => '/out',
                    'username' => 'user',
                    'password' => 'secret',
                    'filename' => 'export.csv',
                    'ssl' => true,
                    'api_url_enabled' => false,
                    'schedule_enabled' => false,
                ]
            ));

        $response->assertStatus(200);
        $this->assertTrue($response->json('ssl'));
        $this->assertTrue($exportMap->fresh()->ssl);
    }

    public function test_update_requires_format()
    {
        $exportMap = ExportMap::factory()->create([
            'type' => 'vehicle',
            'format' => 'csv',
        ]);

        $payload = array_merge($exportMap->toArray(), [
            'ftp_export_enabled' => false,
            'schedule_enabled' => false,
        ]);
        unset($payload['format']);

        $response = $this->actingAs($this->getUser())
            ->putJson("api/settings/export-maps/{$exportMap->id}", $payload);

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

    public function test_update_rejects_invalid_format()
    {
        $exportMap = ExportMap::factory()->create([
            'type' => 'vehicle',
            'format' => 'csv',
        ]);

        $response = $this->actingAs($this->getUser())
            ->putJson("api/settings/export-maps/{$exportMap->id}", array_merge(
                $exportMap->toArray(),
                [
                    'format' => 'pdf',
                    'ftp_export_enabled' => false,
                    'schedule_enabled' => false,
                ]
            ));

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

    public function test_condition_fields_exclude_non_queryable()
    {
        $exportMap = ExportMap::factory()->create(['type' => 'vehicle']);

        $response = $this->actingAs($this->getUser())
            ->getJson("api/settings/export-maps/{$exportMap->id}");

        $response->assertStatus(200);

        $availableFieldIds = collect($response->json('data_options.available_fields'))->pluck('id')->all();
        $conditionFieldIds = collect($response->json('data_options.condition_fields'))->pluck('id')->all();

        // images should be in available_fields but NOT in condition_fields
        $this->assertContains('images', $availableFieldIds);
        $this->assertNotContains('images', $conditionFieldIds);
        $this->assertNotContains('custom1', $conditionFieldIds);
    }

    public function test_show_returns_recent_export_logs_for_the_map()
    {
        $exportMap = ExportMap::factory()->create(['type' => 'vehicle', 'name' => 'Logs Test Feed']);

        SalesChannelHistory::store(
            $exportMap->salesChannelKey(),
            true,
            '5 records exported to feed.json',
            null,
            ['filename' => 'feed.json', 'records' => 5, 'file_verified' => true]
        );

        // History for a different channel must not leak into this map's logs.
        SalesChannelHistory::store('Some Other Channel', false, 'other channel failure');

        $response = $this->actingAs($this->getUser())
            ->getJson("api/settings/export-maps/{$exportMap->id}");

        $response->assertStatus(200);
        $logs = $response->json('logs');
        $this->assertCount(1, $logs);
        $this->assertEquals('success', $logs[0]['status']);
        $this->assertEquals('5 records exported to feed.json', $logs[0]['message']);
        $this->assertTrue($logs[0]['file_verified']);
    }

    public function test_destroy_deletes_export_map()
    {
        $exportMap = ExportMap::factory()->create();

        $response = $this->actingAs($this->getUser())
            ->deleteJson("api/settings/export-maps/{$exportMap->id}");

        $response->assertStatus(200);
        $this->assertNull(ExportMap::find($exportMap->id));
    }
}
