<?php

declare(strict_types=1);

namespace Tests\Feature\Pwa;

use App\Enums\IncomeCategory;
use App\Models\Client;
use App\Models\Company;
use App\Models\Credit;
use App\Models\Income;
use App\Models\Payment;
use App\Models\Plan;
use App\Models\Subscription;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Laravel\Sanctum\Sanctum;
use PHPUnit\Framework\Attributes\Test;
use Spatie\Permission\Models\Role;
use Tests\TestCase;

class AdminDashboardMonthlyInterestTest extends TestCase
{
    use DatabaseTransactions;

    #[Test]
    public function admin_dashboard_exposes_monthly_interest_not_cumulative(): void
    {
        Role::firstOrCreate(['name' => 'admin', 'guard_name' => 'web']);

        $plan = Plan::factory()->create(['has_pwa_access' => true]);
        $company = Company::factory()->create();
        Subscription::factory()->active()->create([
            'company_id' => $company->id,
            'plan_id' => $plan->id,
            'ends_at' => now()->addYear(),
        ]);
        $admin = User::factory()->create(['company_id' => $company->id]);
        $admin->assignRole('admin');

        // Income::create de categoría loan_payment_interest exige payment_id + credit_id
        // válidos (validación de integridad del modelo) y user_id (NOT NULL en la tabla);
        // se crea un crédito + pago mínimos como anclas de esas FKs. El objetivo del test
        // (montos y tendencia de interés) no cambia.
        $client = Client::factory()->create(['company_id' => $company->id]);
        $credit = Credit::create([
            'company_id' => $company->id,
            'client_id' => $client->id,
            'created_by_user_id' => $admin->id,
            'status' => Credit::STATUS_ACTIVE,
            'amount' => 100000,
            'interest_rate' => 20,
            'installments_count' => 4,
            'periodicity' => 'weekly',
            'start_date' => Carbon::now(),
        ]);
        $payment = Payment::create([
            'company_id' => $company->id,
            'credit_id' => $credit->id,
            'amount' => 30000,
            'applied_amount' => 30000,
            'payment_date' => Carbon::now(),
            'registered_by_user_id' => $admin->id,
        ]);

        // Interés ganado ESTE mes: 300.000; mes pasado: 200.000.
        Income::create([
            'company_id' => $company->id,
            'user_id' => $admin->id,
            'credit_id' => $credit->id,
            'payment_id' => $payment->id,
            'category' => IncomeCategory::LOAN_PAYMENT_INTEREST->value,
            'amount' => 300000,
            // Fechado al día 1 de cada mes para robustez en el borde de fin de mes.
            // El dashboard compara "mes en curso hasta hoy" [startOfMonth, now] vs
            // "mismo tramo del mes pasado" [subMonth->startOfMonth, subMonth]; los días
            // 1-2 esas ventanas son muy cortas, así que un ingreso al día 3 (como antes)
            // quedaba fuera → interés 0 y tendencia null. El día 1 siempre cae dentro.
            'operation_date' => now()->startOfMonth()->toDateString(),
            'description' => 'interés mes actual',
        ]);
        Income::create([
            'company_id' => $company->id,
            'user_id' => $admin->id,
            'credit_id' => $credit->id,
            'payment_id' => $payment->id,
            'category' => IncomeCategory::LOAN_PAYMENT_INTEREST->value,
            'amount' => 200000,
            'operation_date' => now()->subMonthNoOverflow()->startOfMonth()->toDateString(),
            'description' => 'interés mes pasado',
        ]);

        Sanctum::actingAs($admin->fresh());

        $stats = $this->getJson('/api/pwa/dashboard')
            ->assertStatus(200)
            ->json('stats');

        $this->assertArrayHasKey('interest_month', $stats);
        $this->assertEquals(300000, $stats['interest_month']['amount']);
        // Tendencia: +50% vs mes pasado (300k vs 200k) → good = true.
        $this->assertEquals(50.0, $stats['interest_month']['trend_pct']);
        $this->assertTrue($stats['interest_month']['good']);
    }
}
