<?php

declare(strict_types=1);

namespace Tests\Feature;

use App\Models\CollectorCreditOrder;
use App\Models\Company;
use App\Models\Credit;
use App\Models\Installment;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use PHPUnit\Framework\Attributes\Test;
use Spatie\Permission\Models\Role;
use Tests\TestCase;

/**
 * #93 — Al marcar un crédito saldado como paid, FixCompletedCredits usaba
 * saveQuietly() (omite el CreditObserver) y no limpiaba collector_credit_order,
 * dejando el crédito pagado en la ruta del cobrador. Ahora despacha
 * CreditStatusSynced y el CollectorSyncListener borra la fila.
 */
class FixCompletedCreditsRouteCleanupTest extends TestCase
{
    use DatabaseTransactions;

    #[Test]
    public function fixing_a_zero_balance_credit_removes_it_from_the_collector_route(): void
    {
        Role::firstOrCreate(['name' => 'collector', 'guard_name' => 'web']);
        $company = Company::factory()->create();
        $collector = User::factory()->create(['company_id' => $company->id]);
        $collector->assignRole('collector');

        // Crédito hoja activo asignado al cobrador → el CreditObserver crea su fila
        // en collector_credit_order al crearse.
        $credit = Credit::factory()->create([
            'company_id' => $company->id,
            'collector_user_id' => $collector->id,
            'status' => Credit::STATUS_ACTIVE,
        ]);

        $this->assertTrue(
            CollectorCreditOrder::where('credit_id', $credit->id)->exists(),
            'Precondición: el crédito activo debe estar en la ruta del cobrador.',
        );

        // Cuota totalmente pagada → saldo 0, pero el crédito sigue 'active'
        // (escenario de red de seguridad que ataca el comando).
        Installment::factory()->create([
            'company_id' => $company->id,
            'credit_id' => $credit->id,
            'installment_number' => 1,
            'status' => Installment::STATUS_PAID,
            'total_amount' => 60000,
            'amount_paid' => 60000,
            'due_date' => now()->subDays(5),
        ]);

        $this->artisan('credify:fix-completed-credits --apply')->assertExitCode(0);

        $this->assertSame(Credit::STATUS_PAID, $credit->fresh()->status);
        $this->assertFalse(
            CollectorCreditOrder::where('credit_id', $credit->id)->exists(),
            'Tras marcarse paid, el crédito no debe seguir en la ruta del cobrador.',
        );
    }
}
