<?php

namespace Tests\Feature;

use App\Domains\Admin\Actions\UpdateTenantTax\UpdateTenantTaxAction;
use App\Domains\Admin\Actions\UpdateTenantTax\UpdateTenantTaxRequest;
use App\Enumerations\TaxExemptionReason;
use App\Enumerations\VatPricingMode;
use App\Models\Tenant;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class TenantTaxInformationTest extends TestCase
{
    use RefreshDatabase;

    private Tenant $tenant;

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

        $this->tenant = Tenant::create([
            'slug' => 'tv',
            'name' => 'Test',
            'email' => 't@example.com',
            'email_finance' => 'finance@example.com',
            'url' => 'test.local',
            'account_name' => 'Test e.V.',
            'account_iban' => 'DE00',
            'account_bic' => 'XY',
            'city' => 'Stadt',
            'postcode' => '00000',
            'is_active_local_group' => true,
            'has_active_instance' => true,
        ]);

        app()->instance('tenant', $this->tenant);
    }

    private function runAction(bool $taxLiable, int $vatRate, ?string $reason, ?string $note = null, string $mode = 'inclusive'): object
    {
        return new UpdateTenantTaxAction(new UpdateTenantTaxRequest(
            tenant: $this->tenant,
            taxLiable: $taxLiable,
            vatRate: $vatRate,
            exemptionReason: $reason ? TaxExemptionReason::where('slug', $reason)->first() : null,
            exemptionNote: $note,
            vatPricingMode: VatPricingMode::from($mode),
        ))->execute();
    }

    public function test_taxable_sets_rate_and_clears_exemption(): void
    {
        $this->tenant->update(['tax_exemption_reason' => 'ustg_19', 'tax_exemption_note' => 'alt']);

        $response = $this->runAction(taxLiable: true, vatRate: 7, reason: null);

        $this->assertTrue($response->success);

        $fresh = $this->tenant->fresh();
        $this->assertTrue($fresh->tax_liable);
        $this->assertSame(7, $fresh->vat_rate);
        $this->assertNull($fresh->tax_exemption_reason);
        $this->assertNull($fresh->tax_exemption_note);
    }

    public function test_exemption_reason_persists_and_clears_rate(): void
    {
        $response = $this->runAction(taxLiable: false, vatRate: 19, reason: 'ustg_4_25a');

        $this->assertTrue($response->success);

        $fresh = $this->tenant->fresh();
        $this->assertFalse($fresh->tax_liable);
        $this->assertSame(0, $fresh->vat_rate);
        $this->assertSame('ustg_4_25a', $fresh->tax_exemption_reason);
        $this->assertNull($fresh->tax_exemption_note);
    }

    public function test_invalid_exemption_reason_fails(): void
    {
        $response = $this->runAction(taxLiable: false, vatRate: 0, reason: 'not_a_reason');

        $this->assertFalse($response->success);
        // Unbekannter Slug wird nicht aufgelöst (null) → kein Speichern, Wert bleibt unverändert.
        $this->assertNull($this->tenant->fresh()->tax_exemption_reason);
    }

    public function test_custom_reason_requires_note(): void
    {
        $missing = $this->runAction(taxLiable: false, vatRate: 0, reason: 'custom', note: '  ');
        $this->assertFalse($missing->success);

        $ok = $this->runAction(taxLiable: false, vatRate: 0, reason: 'custom', note: 'Individueller Grund');
        $this->assertTrue($ok->success);
        $this->assertSame('Individueller Grund', $this->tenant->fresh()->tax_exemption_note);
    }

    public function test_vat_rate_is_clamped(): void
    {
        $this->runAction(taxLiable: true, vatRate: 250, reason: null);
        $this->assertSame(100, $this->tenant->fresh()->vat_rate);
    }

    public function test_pricing_mode_persists_when_liable(): void
    {
        $this->runAction(taxLiable: true, vatRate: 19, reason: null, mode: 'add_on');
        $this->assertSame('add_on', $this->tenant->fresh()->vat_pricing_mode);
    }

    public function test_pricing_mode_resets_to_inclusive_when_exempt(): void
    {
        $this->runAction(taxLiable: false, vatRate: 0, reason: 'ustg_19', mode: 'add_on');
        $this->assertSame('inclusive', $this->tenant->fresh()->vat_pricing_mode);
    }

    public function test_invoice_text_per_reason(): void
    {
        $this->assertSame(
            'Gemäß § 19 UStG wird keine Umsatzsteuer berechnet.',
            TaxExemptionReason::where('slug', 'ustg_19')->first()->invoiceText(),
        );
        $this->assertSame(
            'Die Leistung ist gemäß § 4 Nr. 25 Buchst. a UStG von der Umsatzsteuer befreit.',
            TaxExemptionReason::where('slug', 'ustg_4_25a')->first()->invoiceText(),
        );
        $this->assertSame(
            'Die Leistung ist gemäß § 4 Nr. 24 UStG von der Umsatzsteuer befreit.',
            TaxExemptionReason::where('slug', 'ustg_4_24')->first()->invoiceText(),
        );
        // Freitext-Grund liefert den mitgegebenen Text statt eines festen Rechnungshinweises.
        $this->assertSame('Mein Text', TaxExemptionReason::where('slug', 'custom')->first()->invoiceText('Mein Text'));
    }

    public function test_options_are_ordered(): void
    {
        $slugs = array_column(TaxExemptionReason::options(), 'value');
        $this->assertSame(['ustg_19', 'ustg_4_24', 'ustg_4_25a', 'ustg_4_22a', 'custom'], $slugs);
    }
}
