<?php

namespace Tests\Unit;

use App\Enums\CreditAuditEvent;
use PHPUnit\Framework\TestCase;

class CreditAuditEventTest extends TestCase
{
    public function test_all_cases_have_label(): void
    {
        foreach (CreditAuditEvent::cases() as $case) {
            $label = $case->label();
            $this->assertNotEmpty($label, "Case {$case->value} should have a label");
            $this->assertIsString($label);
        }
    }

    public function test_all_cases_have_category(): void
    {
        $validCategories = ['financial', 'structural', 'administrative'];

        foreach (CreditAuditEvent::cases() as $case) {
            $category = $case->category();
            $this->assertContains(
                $category,
                $validCategories,
                "Case {$case->value} has invalid category: {$category}"
            );
        }
    }

    public function test_all_cases_have_icon(): void
    {
        foreach (CreditAuditEvent::cases() as $case) {
            $icon = $case->icon();
            $this->assertStringStartsWith('heroicon-o-', $icon, "Case {$case->value} icon must start with heroicon-o-");
        }
    }

    public function test_all_cases_have_color(): void
    {
        $validColors = ['success', 'warning', 'danger', 'info', 'gray', 'purple'];

        foreach (CreditAuditEvent::cases() as $case) {
            $color = $case->color();
            $this->assertContains(
                $color,
                $validColors,
                "Case {$case->value} has invalid color: {$color}"
            );
        }
    }

    public function test_structural_category_matches_legacy_method(): void
    {
        foreach (CreditAuditEvent::cases() as $case) {
            $this->assertSame(
                $case->category() === 'structural',
                $case->isStructuralOperation(),
                "Case {$case->value}: category() and isStructuralOperation() are inconsistent"
            );
        }
    }

    public function test_structural_events(): void
    {
        $structuralEvents = [
            CreditAuditEvent::CREDIT_EXTENDED,
            CreditAuditEvent::CREDIT_EXTENDED_WITH_INTEREST,
            CreditAuditEvent::CREDIT_REFINANCED,
            CreditAuditEvent::CREDIT_RESTRUCTURED,
            CreditAuditEvent::CREDIT_RENEWED,
        ];

        foreach ($structuralEvents as $event) {
            $this->assertSame('structural', $event->category());
        }
    }

    public function test_administrative_events(): void
    {
        $adminEvents = [
            CreditAuditEvent::CREDIT_CREATED,
            CreditAuditEvent::CREDIT_CANCELED,
            CreditAuditEvent::CREDIT_EDITED,
            CreditAuditEvent::CREDIT_CLONED,
            CreditAuditEvent::CREDIT_CLONED_EDITABLE,
            CreditAuditEvent::INSTALLMENTS_GENERATED,
            CreditAuditEvent::INSTALLMENTS_REGENERATED,
        ];

        foreach ($adminEvents as $event) {
            $this->assertSame('administrative', $event->category());
        }
    }

    public function test_summary_with_empty_data_returns_only_label(): void
    {
        foreach (CreditAuditEvent::cases() as $case) {
            $summary = $case->summary([]);
            $this->assertSame(
                $case->label(),
                $summary,
                "Case {$case->value}: summary with empty data should return only label"
            );
        }
    }

    public function test_summary_does_not_invent_data(): void
    {
        // Con datos que no contienen campos reconocidos
        $data = ['unknown_field' => 'value'];
        $summary = CreditAuditEvent::CREDIT_CREATED->summary($data);

        $this->assertSame('Crédito creado', $summary);
    }

    public function test_summary_with_new_credit_id(): void
    {
        $data = ['new_credit_id' => 456];
        $summary = CreditAuditEvent::CREDIT_REFINANCED->summary($data);

        $this->assertStringContainsString('Crédito refinanciado', $summary);
        $this->assertStringContainsString('crédito #456', $summary);
    }

    public function test_summary_with_input_amount(): void
    {
        $data = ['input' => ['amount' => 5000]];
        $summary = CreditAuditEvent::CREDIT_CREATED->summary($data);

        $this->assertStringContainsString('Crédito creado', $summary);
        $this->assertStringContainsString('Monto:', $summary);
    }

    public function test_summary_with_installments(): void
    {
        $data = ['input' => ['new_installments' => 18]];
        $summary = CreditAuditEvent::CREDIT_EXTENDED->summary($data);

        $this->assertStringContainsString('Crédito extendido', $summary);
        $this->assertStringContainsString('18 cuotas', $summary);
    }

    public function test_summary_with_additional_capital(): void
    {
        $data = [
            'input' => ['additional_capital' => 2000, 'new_installments' => 12],
            'new_credit_id' => 789,
        ];
        $summary = CreditAuditEvent::CREDIT_REFINANCED->summary($data);

        $this->assertStringContainsString('Crédito refinanciado', $summary);
        $this->assertStringContainsString('Capital adicional:', $summary);
        $this->assertStringContainsString('12 cuotas', $summary);
        $this->assertStringContainsString('crédito #789', $summary);
    }

    public function test_summary_never_includes_non_persisted_fields(): void
    {
        // Simular data sin monto — no debe decir nada de monto
        $data = ['input' => ['periodicity' => 'monthly']];
        $summary = CreditAuditEvent::CREDIT_CREATED->summary($data);

        $this->assertStringNotContainsString('Monto', $summary);
        $this->assertStringNotContainsString('cuotas', $summary);
        $this->assertStringNotContainsString('crédito #', $summary);
    }
}
