<?php

declare(strict_types=1);

namespace App\Filament\Widgets\Admin;

use App\Models\CapitalContribution;
use App\Models\Partner;
use App\Models\PartnerWithdrawal;
use App\ValueObjects\Money;
use Carbon\Carbon;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Illuminate\Support\Facades\Auth;

/**
 * Widget de Capital e Inversiones — Panel Gerencial.
 *
 * ── CORRECCIÓN DE BUG (RCA) ──────────────────────────────────────────────
 * El bug original en la tarjeta "Utilidades distribuidas" tenía las
 * métricas acopladas a DOS tablas distintas:
 *
 *   VALOR       → partner_withdrawals  (retiros aprobados de tipo profit/dividend)
 *   DESCRIPCIÓN → profit_distributions (workflow formal DRAFT→APPROVED→DISTRIBUTED)
 *
 * Cuando los retiros se registran directamente (sin pasar por el workflow de
 * ProfitDistribution), `profit_distributions` queda vacía y la query de la
 * descripción retorna NULL → texto "Sin distribuciones ejecutadas" contradice
 * el saldo real.
 *
 * FIX: la "última distribución" ahora se obtiene de partner_withdrawals
 * (mismo origen que el valor), usando operation_date DESC. Ambas métricas
 * son coherentes independientemente del flujo usado para crear los retiros.
 * ─────────────────────────────────────────────────────────────────────────
 */
class PartnerCapitalWidget extends BaseWidget
{
    protected ?string $pollingInterval = '120s';

    protected static ?int $sort = 8;

    protected int|string|array $columnSpan = 'full';

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

        return $user && $user->hasAnyRole(['admin', 'super_admin']);
    }

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

        if (! $companyId && ! $user->isSuperAdmin()) {
            return [];
        }

        // Scope multi-tenant reutilizable
        $scope = fn ($query) => $user->isSuperAdmin()
            ? $query
            : $query->where('company_id', $companyId);

        // ── 1. Capital bruto aportado ──────────────────────────────────────
        // CapitalContribution no tiene approval_status: cada aporte ya está
        // vinculado a un Income (income_id), por lo que su existencia en tabla
        // garantiza que fue procesado contablemente.
        $totalContributions = Money::of(
            $scope(CapitalContribution::query())->sum('amount')
        );

        $contributionsCount = $scope(CapitalContribution::query())->count();

        // ── 2. Capital devuelto (solo capital_return aprobados) ────────────
        // profit_withdrawal y dividend_payment NO reducen equity, son P&L.
        $totalCapitalReturned = Money::of(
            $scope(PartnerWithdrawal::query())
                ->where('approval_status', 'approved')
                ->where('type', 'capital_return')
                ->sum('amount')
        );

        // ── 3. Capital neto (patrimonio real invertido) ────────────────────
        $netCapital = $totalContributions->subtract($totalCapitalReturned);

        $capitalReturnedLabel = $totalCapitalReturned->isZero()
            ? 'Sin devoluciones de capital'
            : $totalCapitalReturned->formatWithCurrency().' devuelto(s)';

        // ── 4. Utilidades distribuidas ─────────────────────────────────────
        // FUENTE CORREGIDA: partner_withdrawals (mismo origen que el valor).
        // Se suman retiros APROBADOS de tipo profit_withdrawal y dividend_payment.
        $totalProfitsDistributed = Money::of(
            $scope(PartnerWithdrawal::query())
                ->where('approval_status', 'approved')
                ->whereIn('type', ['profit_withdrawal', 'dividend_payment'])
                ->sum('amount')
        );

        // Última fecha de distribución: operation_date del retiro más reciente
        // aprobado de tipo profit/dividend. Coherente con el valor mostrado.
        $lastDistributionDate = $scope(PartnerWithdrawal::query())
            ->where('approval_status', 'approved')
            ->whereIn('type', ['profit_withdrawal', 'dividend_payment'])
            ->orderByDesc('operation_date')
            ->value('operation_date');

        $lastDistributionLabel = $lastDistributionDate
            ? 'Última dist.: '.Carbon::parse($lastDistributionDate)->format('d M Y')
            : 'Sin distribuciones ejecutadas';

        // Retiros de utilidades pendientes de aprobación (alerta operacional)
        $pendingProfitWithdrawals = $scope(PartnerWithdrawal::query())
            ->where('approval_status', 'pending')
            ->whereIn('type', ['profit_withdrawal', 'dividend_payment'])
            ->count();

        // ── 5. Socios activos y retiros pendientes totales ─────────────────
        $activePartners = $scope(Partner::query())
            ->where('status', 'active')
            ->count();

        $totalPartners = $scope(Partner::query())->count();

        $pendingWithdrawalsTotal = $scope(PartnerWithdrawal::query())
            ->where('approval_status', 'pending')
            ->count();

        $partnersDescription = $totalPartners > 0
            ? "{$activePartners} de {$totalPartners} ".($totalPartners === 1 ? 'socio' : 'socios')
            : 'Sin socios registrados';

        return [

            // ── Tarjeta 1: Capital total aportado ─────────────────────────
            Stat::make('Capital Aportado', $totalContributions->formatWithCurrency())
                ->description($contributionsCount > 0
                    ? $contributionsCount.' '.($contributionsCount === 1 ? 'aporte registrado' : 'aportes registrados')
                    : 'Sin aportes registrados'
                )
                ->descriptionIcon('heroicon-o-arrow-down-circle')
                ->color('success'),

            // ── Tarjeta 2: Patrimonio neto ────────────────────────────────
            Stat::make('Capital Neto (Equity)', $netCapital->formatWithCurrency())
                ->description($capitalReturnedLabel)
                ->descriptionIcon('heroicon-o-building-library')
                ->color(match (true) {
                    $netCapital->isPositive() => 'primary',
                    $netCapital->isZero() => 'warning',
                    default => 'danger',   // capital negativo: error contable
                }),

            // ── Tarjeta 3: Utilidades distribuidas ────────────────────────
            // Descripción dinámica: prioriza alerta de pendientes > última fecha.
            Stat::make('Utilidades Distribuidas', $totalProfitsDistributed->formatWithCurrency())
                ->description($pendingProfitWithdrawals > 0
                    ? $pendingProfitWithdrawals.' retiro(s) por aprobar'
                    : $lastDistributionLabel
                )
                ->descriptionIcon($pendingProfitWithdrawals > 0
                    ? 'heroicon-o-exclamation-triangle'
                    : ($totalProfitsDistributed->isZero()
                        ? 'heroicon-o-clock'
                        : 'heroicon-o-chart-pie')
                )
                ->color($pendingProfitWithdrawals > 0 ? 'warning' : 'info'),

            // ── Tarjeta 4: Socios activos ─────────────────────────────────
            Stat::make('Socios Activos', (string) $activePartners)
                ->description($pendingWithdrawalsTotal > 0
                    ? $pendingWithdrawalsTotal.' retiro(s) pendiente(s) de aprobación'
                    : $partnersDescription
                )
                ->descriptionIcon($pendingWithdrawalsTotal > 0
                    ? 'heroicon-o-exclamation-circle'
                    : 'heroicon-o-user-group'
                )
                ->color($pendingWithdrawalsTotal > 0 ? 'warning' : 'success'),

        ];
    }
}
