<?php

namespace Tests\Tenant;

use Mtc\MercuryDataModels\OfferFinanceFieldConfig;
use Mtc\MercuryDataModels\VehicleOffer;
use Mtc\MercuryDataModels\VehicleOfferFinance;
use Tests\TenantTestCase;
use Tests\UserForTenant;

class OfferFinanceFieldConfigTest extends TenantTestCase
{
    use UserForTenant;

    public function testIndex(): void
    {
        OfferFinanceFieldConfig::factory()->count(3)->create();

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.finance-fields.index'));

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

    public function testIndexOrdersByPosition(): void
    {
        OfferFinanceFieldConfig::factory()->create(['key' => 'b_field', 'position' => 5]);
        OfferFinanceFieldConfig::factory()->create(['key' => 'a_field', 'position' => 1]);
        OfferFinanceFieldConfig::factory()->create(['key' => 'c_field', 'position' => 3]);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.finance-fields.index'));

        $response->assertStatus(200);
        $keys = collect($response->json('data'))->pluck('description')->all();
        $this->assertSame(['a_field', 'c_field', 'b_field'], $keys);
    }

    public function testStore(): void
    {
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.finance-fields.store'), [
                'key' => 'mangoletsi_saving',
                'label' => 'Mangoletsi Saving',
                'type' => 'currency',
                'position' => 2,
            ]);

        $response->assertStatus(201);
        $this->assertEquals('mangoletsi_saving', $response->json('config.key'));
        $this->assertEquals('Mangoletsi Saving', $response->json('config.label'));
        $this->assertEquals('currency', $response->json('config.type'));
        $this->assertDatabaseHas('offer_finance_field_configs', [
            'key' => 'mangoletsi_saving',
        ]);
    }

    public function testStoreDerivesKeyFromLabelWhenMissing(): void
    {
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.finance-fields.store'), [
                'label' => 'Mangoletsi Saving',
                'type' => 'currency',
            ]);

        $response->assertStatus(201);
        $this->assertEquals('mangoletsi_saving', $response->json('config.key'));
    }

    public function testStoreRejectsDuplicateKey(): void
    {
        OfferFinanceFieldConfig::factory()->create(['key' => 'mg_saving_fda']);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.finance-fields.store'), [
                'key' => 'mg_saving_fda',
                'label' => 'MG Saving FDA',
                'type' => 'currency',
            ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors('key');
    }

    public function testStoreRejectsInvalidKeyFormat(): void
    {
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.finance-fields.store'), [
                'key' => 'Bad-Key',
                'label' => 'Bad',
                'type' => 'text',
            ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors('key');
    }

    public function testStoreRejectsInvalidType(): void
    {
        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->postJson(route('tenant.finance-fields.store'), [
                'key' => 'foo',
                'label' => 'Foo',
                'type' => 'json',
            ]);

        $response->assertStatus(422);
        $response->assertJsonValidationErrors('type');
    }

    public function testShow(): void
    {
        $config = OfferFinanceFieldConfig::factory()->create();

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

        $response->assertStatus(200);
        $this->assertEquals($config->id, $response->json('config.id'));
        $this->assertEquals($config->key, $response->json('config.key'));
    }

    public function testUpdate(): void
    {
        $config = OfferFinanceFieldConfig::factory()->create([
            'key' => 'old_key',
            'label' => 'Old',
            'type' => 'text',
        ]);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.finance-fields.update', $config), [
                'label' => 'New label',
                'type' => 'currency',
                'suffix' => '/mo',
            ]);

        $response->assertStatus(200);
        $this->assertEquals('New label', $response->json('config.label'));
        $this->assertEquals('currency', $response->json('config.type'));
        $this->assertEquals('/mo', $response->json('config.suffix'));
        $this->assertEquals('old_key', $response->json('config.key'));
    }

    public function testUpdateAllowsKeepingOwnKey(): void
    {
        $config = OfferFinanceFieldConfig::factory()->create(['key' => 'same_key']);

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->putJson(route('tenant.finance-fields.update', $config), [
                'key' => 'same_key',
                'label' => 'Edited',
                'type' => 'text',
            ]);

        $response->assertStatus(200);
    }

    public function testDestroy(): void
    {
        $config = OfferFinanceFieldConfig::factory()->create();

        $response = $this->actingAs($this->getUser())
            ->withHeader('X-Tenant', tenant('id'))
            ->deleteJson(route('tenant.finance-fields.destroy', $config));

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

    public function testRequiresAuthentication(): void
    {
        $response = $this->withHeader('X-Tenant', tenant('id'))
            ->getJson(route('tenant.finance-fields.index'));

        $response->assertStatus(401);
    }

    public function testFinanceDataJsonRoundTripsThroughTenantExtras(): void
    {
        $offer = VehicleOffer::factory()->create();

        $finance = $offer->finance()->create([
            'finance_type' => 'pcp',
            'monthly_price' => 200,
            'term' => 36,
            'data' => [
                'mangoletsi_saving' => 1500,
                'mg_saving_fda' => 750,
            ],
        ]);

        $reloaded = VehicleOfferFinance::query()->findOrFail($finance->id);
        $this->assertSame(1500, $reloaded->data['mangoletsi_saving']);
        $this->assertSame(750, $reloaded->data['mg_saving_fda']);
    }
}
