<?php

declare(strict_types=1);

namespace App\Filament\Widgets\Admin;

use App\Services\Dashboard\AdminDashboardMetricsService;
use App\Services\Metrics\BusinessMetricsService;
use Carbon\Carbon;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Illuminate\Support\Facades\Auth;

/**
 * Rentabilidad real del negocio — los MISMOS numeros que la PWA del dueno.
 *
 * Lee del mismo BusinessMetricsService que el payload de la app, asi que las
 * dos superficies no pueden mostrar cifras distintas.
 *
 * El interes se deriva del ledger de cuotas (imputacion interes-primero), no de
 * `incomes`: los pagos se registran con la categoria generica `payment`, que es
 * la razon por la que "Utilidad mes" marcaba $0.
 */
class ProfitabilityWidget extends BaseWidget
{
    protected ?string $pollingInterval = '120s';

    protected static ?int $sort = 1;

    protected ?string $heading = 'Rentabilidad (últimos 30 días)';

    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;
        $hoy = Carbon::today();

        $service = app(BusinessMetricsService::class);
        $actual = $service->forPeriod($companyId, $hoy->copy()->subDays(29), $hoy->copy());
        $previo = $service->forPeriod($companyId, $hoy->copy()->subDays(59), $hoy->copy()->subDays(30));

        $delta = $previo['net_profit'] > 0.0
            ? round((($actual['net_profit'] - $previo['net_profit']) / $previo['net_profit']) * 100, 1)
            : null;

        // Sin costos cargados la "utilidad" es el interes bruto con otro nombre.
        // Se advierte en vez de presumir un margen sano.
        $sinCostos = $actual['operating_expenses'] <= 0.0;

        return [
            Stat::make('Utilidad neta', $this->money($actual['net_profit']))
                ->description($sinCostos
                    ? 'sin costos registrados: es prácticamente el interés bruto'
                    : ($delta === null
                        ? 'sin base de comparación'
                        : sprintf('%s %s%% vs 30 días previos', $delta >= 0 ? '▲' : '▼', abs($delta))))
                ->color($sinCostos ? 'warning' : (($delta ?? 0) >= 0 ? 'success' : 'danger')),

            Stat::make('Interés cobrado', $this->money($actual['interest_collected']))
                ->description('ganancia bruta de la cartera')
                ->color('success'),

            Stat::make(
                'Margen',
                $actual['margin'] === null ? 'sin datos' : number_format($actual['margin'], 1, ',', '.').'%'
            )
                ->description($actual['margin'] === null
                    ? 'sin ingresos de utilidad en el periodo'
                    : ($sinCostos ? 'no hay costos registrados en el periodo' : 'utilidad sobre ingresos'))
                ->color($sinCostos ? 'warning' : 'success'),

            // Cuarto indicador, para tener la MISMA paridad que la PWA.
            Stat::make('Rendimiento mensual', $this->rendimiento($companyId, $actual['net_profit']))
                ->description('utilidad sobre patrimonio')
                ->color('success'),
        ];
    }

    /** Utilidad del periodo sobre el patrimonio actual, mensualizado. */
    private function rendimiento(int $companyId, float $netProfit): string
    {
        $patrimonio = (float) (app(AdminDashboardMetricsService::class)
            ->getMetrics($companyId)['business_total']['amount'] ?? 0);

        if ($patrimonio <= 0.0) {
            return 'sin datos';
        }

        return number_format(($netProfit / $patrimonio) * 100, 1, ',', '.').'%';
    }

    private function money(float $amount): string
    {
        return '$'.number_format($amount, 0, ',', '.');
    }
}
