<?php

declare(strict_types=1);

namespace Tests\Feature;

use App\Models\Client;
use App\Models\Company;
use App\Models\Credit;
use App\Models\FinancialOperation;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;

/**
 * #187 — el medidor de volumen mensual (`max_monthly_volume`) suma, sin doble-contar:
 *  (1) el `amount` de los créditos RAÍZ nuevos del mes, y
 *  (2) la caja NUEVA (`FinancialOperation.cash_out`) de operaciones sobre HIJOS.
 *
 * Así cuenta el capital adicional de refinanciar y la diferencia de renovar (dinero nuevo
 * real que antes se escapaba al excluir a todos los hijos, #172), pero NO el saldo que solo
 * se redistribuye (extender/reestructurar → `cash_out` 0). Excluye hijos cancelados.
 */
class CurrentMonthDisbursedVolumeTest extends TestCase
{
    use DatabaseTransactions;

    private Company $company;

    private User $user;

    private Client $client;

    protected function setUp(): void
    {
        parent::setUp();
        $this->company = Company::factory()->create(['interest_method' => 'flat_rate']);
        $this->user = User::factory()->create(['company_id' => $this->company->id]);
        $this->client = Client::factory()->create(['company_id' => $this->company->id]);
    }

    private function credit(string $status = Credit::STATUS_ACTIVE, ?int $parentId = null, float $amount = 100000): Credit
    {
        return Credit::create([
            'company_id' => $this->company->id,
            'client_id' => $this->client->id,
            'created_by_user_id' => $this->user->id,
            'parent_credit_id' => $parentId,
            'status' => $status,
            'amount' => $amount,
            'interest_rate' => 10,
            'installments_count' => 4,
            'periodicity' => 'weekly',
            'start_date' => Carbon::now(),
        ]);
    }

    private function op(array $attrs): FinancialOperation
    {
        return FinancialOperation::create(array_merge([
            'company_id' => $this->company->id,
            'user_id' => $this->user->id,
            'cash_in' => 0,
        ], $attrs));
    }

    #[Test]
    public function it_counts_root_loans_plus_new_cash_from_refinance_and_ignores_extend_and_canceled(): void
    {
        $root = $this->credit(amount: 600000);                                  // préstamo nuevo → 600.000 por `amount`
        $refiChild = $this->credit(parentId: $root->id);                        // hijo de refinanciación
        $extChild = $this->credit(parentId: $root->id);                         // hijo de extensión
        $canceledChild = $this->credit(Credit::STATUS_CANCELED, $root->id);     // hijo cancelado

        // Refinanciar: capital adicional 300.000 (800.000 nuevo − 500.000 rolado).
        $this->op(['operation_type' => 'credit_refinance', 'source_credit_id' => $root->id, 'target_credit_id' => $refiChild->id, 'credit_amount' => 800000, 'compensated_amount' => 500000, 'cash_out' => 300000]);
        // Extender: solo redistribuye → cash_out 0 (no infla).
        $this->op(['operation_type' => 'credit_extension', 'source_credit_id' => $root->id, 'target_credit_id' => $extChild->id, 'credit_amount' => 400000, 'compensated_amount' => 400000, 'cash_out' => 0]);
        // Hijo cancelado con caja → se excluye.
        $this->op(['operation_type' => 'credit_disbursement', 'target_credit_id' => $canceledChild->id, 'credit_amount' => 999000, 'compensated_amount' => 0, 'cash_out' => 999000]);

        // 600.000 (raíz) + 300.000 (adicional de refinanciación) + 0 (extensión) = 900.000.
        $this->assertEqualsWithDelta(900000, $this->company->currentMonthDisbursedVolume(), 0.01);
    }

    #[Test]
    public function it_only_counts_the_current_month(): void
    {
        $root = $this->credit(amount: 500000);
        $root->forceFill(['created_at' => Carbon::now()->subMonthNoOverflow()])->saveQuietly();

        $this->assertEqualsWithDelta(0, $this->company->currentMonthDisbursedVolume(), 0.01);
    }
}
