<?php

declare(strict_types=1);

namespace App\Filament\Widgets\Admin;

use App\Services\Metrics\CashFlowMetricsService;
use App\Services\Metrics\PortfolioMetricsService;
use App\ValueObjects\Money;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Illuminate\Support\Facades\Auth;

/**
 * KPIs Globales de Inteligencia de Negocios — Admin.
 *
 * Muestra las tres métricas maestras del negocio:
 *   - Caja Actual   : Efectivo líquido disponible (Opening Balance + Ingresos - Egresos aprobados).
 *   - Saldo por Cobrar: Capital activo en la calle (SUM total_amount - amount_paid en cuotas
 *                       de créditos hoja activos, sin tocar principal_balance_after).
 *   - Valor del Negocio: Caja + Saldo por Cobrar.  Refleja el valor económico total operado.
 */
class BusinessKPIsWidget extends BaseWidget
{
    protected ?string $pollingInterval = '120s';

    protected static ?int $sort = 0;

    protected ?string $heading = 'KPIs Globales del Negocio';

    // Fuerza ancho completo en el header grid (getHeaderWidgetsColumns = 1 en Admin).
    protected int|string|array $columnSpan = 'full';

    public static function canView(): bool
    {
        $user = Auth::user();

        return $user && $user->hasRole('admin') && ! $user->isSuperAdmin();
    }

    protected function getStats(): array
    {
        $companyId = (int) Auth::user()->company_id;

        $cashFlowService = app(CashFlowMetricsService::class);
        $portfolioService = app(PortfolioMetricsService::class);

        // Caja Actual: Opening Balance + todos los ingresos (excl. OPENING_BALANCE) - egresos aprobados que afectan caja.
        $cashPosition = $cashFlowService->getCashPosition($companyId);

        // Saldo por Cobrar: SUM(total_amount - amount_paid) de cuotas no pagadas en créditos hoja activos.
        // Usa un único agregado SQL — no carga colecciones Eloquent en memoria.
        $portfolioBalance = $portfolioService->getActivePortfolioBalance($companyId);

        // Valor del Negocio: suma directa con Money para conservar precisión BC Math.
        $businessValue = Money::of($cashPosition)->add($portfolioBalance)->value();

        return [
            Stat::make('Caja Actual', $this->formatCurrency($cashPosition))
                ->description('Efectivo líquido disponible')
                ->descriptionIcon('heroicon-m-currency-dollar')
                ->color($cashPosition >= 0 ? 'success' : 'danger'),

            Stat::make('Saldo por Cobrar', $this->formatCurrency($portfolioBalance))
                ->description('Capital activo en la calle')
                ->descriptionIcon('heroicon-m-banknotes')
                ->color('primary'),

            Stat::make('Valor del Negocio', $this->formatCurrency($businessValue))
                ->description('Caja + Cartera activa')
                ->descriptionIcon('heroicon-m-building-library')
                ->color('info'),
        ];
    }

    private function formatCurrency(float $amount): string
    {
        $prefix = $amount < 0 ? '-' : '';

        return $prefix.'$'.number_format(abs($amount), 0, ',', '.');
    }
}
