<?php

declare(strict_types=1);

namespace App\Enums;

/**
 * Categorías de Ingresos del Sistema Credify.
 *
 * MODELO DE CATEGORÍAS (Phase 1 - Enhanced Accounting):
 * ======================================================
 *
 * 1. INGRESOS VINCULADOS A PAGOS (requieren payment_id y credit_id):
 *    - payment: [LEGACY] Pago normal - será migrado a principal+interest
 *    - loan_payment_principal: Porción de capital recuperado
 *    - loan_payment_interest: Porción de interés ganado
 *    - overpayment: Excedente de pago (saldo a favor del cliente)
 *
 * 2. TRANSACCIONES DE CAPITAL (afectan patrimonio, no P&L):
 *    - capital_injection: Inyección de capital del propietario
 *    - investor_contribution: Aporte de inversionista externo
 *    - opening_balance: Balance inicial del sistema
 *
 * 3. INGRESOS OPERATIVOS (afectan P&L como ingresos):
 *    - late_fee: Cargo por pago tardío
 *    - penalty_interest: Interés moratorio
 *    - service_fee: Comisión por servicios
 *    - recovery_bad_debt: Recuperación de cartera castigada
 *    - other_operational: Otros ingresos operativos
 *
 * REGLAS DE IMPACTO FINANCIERO:
 * =============================
 * - affects_cash: ¿Incrementa el efectivo disponible?
 * - affects_capital: ¿Incrementa el capital de trabajo?
 * - affects_profit: ¿Incrementa las utilidades del período?
 */
enum IncomeCategory: string
{
    // ═══════════════════════════════════════════════════════════════════════
    // PAYMENT-LINKED CATEGORIES (require payment_id, system-generated)
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * @deprecated Use LOAN_PAYMENT_PRINCIPAL + LOAN_PAYMENT_INTEREST instead
     * Mantained for backward compatibility during migration
     */
    case PAYMENT = 'payment';

    /**
     * Principal portion of a loan payment.
     * This is CAPITAL RECOVERY, not profit.
     */
    case LOAN_PAYMENT_PRINCIPAL = 'loan_payment_principal';

    /**
     * Interest portion of a loan payment.
     * This is PROFIT/REVENUE.
     */
    case LOAN_PAYMENT_INTEREST = 'loan_payment_interest';

    /**
     * Customer overpayment - creates a liability (credit balance).
     * Does NOT affect profit until applied.
     */
    case OVERPAYMENT = 'overpayment';

    // ═══════════════════════════════════════════════════════════════════════
    // CAPITAL TRANSACTIONS (affect equity, NOT profit)
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Owner/partner capital injection.
     * Increases CAPITAL and CASH, but NOT profit.
     */
    case CAPITAL_INJECTION = 'capital_injection';

    /**
     * @deprecated Use CAPITAL_INJECTION instead
     * Mantained for backward compatibility
     */
    case PARTNER_CONTRIBUTION = 'partner_contribution';

    /**
     * External investor contribution.
     * Increases CAPITAL and CASH, but NOT profit.
     */
    case INVESTOR_CONTRIBUTION = 'investor_contribution';

    /**
     * System opening balance.
     * Establishes initial CAPITAL and CASH. Once set, cannot be changed.
     */
    case OPENING_BALANCE = 'opening_balance';

    // ═══════════════════════════════════════════════════════════════════════
    // OPERATIONAL INCOME (affect P&L as revenue)
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Late payment fee charged to customer.
     * Pure PROFIT - does not affect capital.
     */
    case LATE_FEE = 'late_fee';

    /**
     * Penalty interest (mora) charged on overdue amounts.
     * Pure PROFIT - does not affect capital.
     */
    case PENALTY_INTEREST = 'penalty_interest';

    /**
     * Service/administrative fee.
     * Pure PROFIT - does not affect capital.
     */
    case SERVICE_FEE = 'service_fee';

    /**
     * Recovery of previously written-off bad debt.
     * Affects PROFIT (recovery income) and may affect capital depending on accounting treatment.
     */
    case RECOVERY_BAD_DEBT = 'recovery_bad_debt';

    /**
     * @deprecated Use RECOVERY_BAD_DEBT instead
     * Mantained for backward compatibility
     */
    case RECOVERY = 'recovery';

    /**
     * @deprecated Use specific categories (LATE_FEE, PENALTY_INTEREST, SERVICE_FEE)
     * Mantained for backward compatibility
     */
    case EXTRA_CHARGE = 'extra_charge';

    /**
     * Other operational income not classified elsewhere.
     * Affects PROFIT.
     */
    case OTHER_OPERATIONAL = 'other_operational';

    /**
     * @deprecated Use OTHER_OPERATIONAL instead
     * Mantained for backward compatibility
     */
    case OTHER_INCOME = 'other_income';

    // ═══════════════════════════════════════════════════════════════════════
    // CATEGORY GROUPING METHODS
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Categories that REQUIRE payment_id and credit_id.
     */
    public static function paymentLinkedCategories(): array
    {
        return [
            self::PAYMENT,
            self::LOAN_PAYMENT_PRINCIPAL,
            self::LOAN_PAYMENT_INTEREST,
            self::OVERPAYMENT,
        ];
    }

    /**
     * Capital transaction categories (affect equity, not P&L).
     */
    public static function capitalCategories(): array
    {
        return [
            self::CAPITAL_INJECTION,
            self::PARTNER_CONTRIBUTION, // Legacy
            self::INVESTOR_CONTRIBUTION,
            self::OPENING_BALANCE,
        ];
    }

    /**
     * Operational income categories (affect P&L).
     */
    public static function operationalCategories(): array
    {
        return [
            self::LATE_FEE,
            self::PENALTY_INTEREST,
            self::SERVICE_FEE,
            self::RECOVERY_BAD_DEBT,
            self::RECOVERY, // Legacy
            self::EXTRA_CHARGE, // Legacy
            self::OTHER_OPERATIONAL,
            self::OTHER_INCOME, // Legacy
        ];
    }

    /**
     * Legacy categories that should be migrated.
     */
    public static function legacyCategories(): array
    {
        return [
            self::PAYMENT,
            self::PARTNER_CONTRIBUTION,
            self::RECOVERY,
            self::EXTRA_CHARGE,
            self::OTHER_INCOME,
        ];
    }

    /**
     * Categories available for manual creation in UI.
     */
    public static function manualCreationCategories(): array
    {
        return [
            // Capital
            self::CAPITAL_INJECTION,
            self::INVESTOR_CONTRIBUTION,
            self::OPENING_BALANCE,
            // Operational
            self::LATE_FEE,
            self::PENALTY_INTEREST,
            self::SERVICE_FEE,
            self::RECOVERY_BAD_DEBT,
            self::OTHER_OPERATIONAL,
        ];
    }

    // ═══════════════════════════════════════════════════════════════════════
    // BOOLEAN CHECK METHODS
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Is this category linked to a payment?
     */
    public function isPaymentLinked(): bool
    {
        return in_array($this, self::paymentLinkedCategories(), true);
    }

    /**
     * Is this a capital transaction?
     */
    public function isCapitalTransaction(): bool
    {
        return in_array($this, self::capitalCategories(), true);
    }

    /**
     * Is this operational income?
     */
    public function isOperational(): bool
    {
        return in_array($this, self::operationalCategories(), true);
    }

    /**
     * Is this a legacy category that should be migrated?
     */
    public function isLegacy(): bool
    {
        return in_array($this, self::legacyCategories(), true);
    }

    /**
     * Can this category be created manually in UI?
     */
    public function canBeCreatedManually(): bool
    {
        return in_array($this, self::manualCreationCategories(), true);
    }

    /**
     * Does this category require payment_id?
     */
    public function requiresPaymentId(): bool
    {
        return $this->isPaymentLinked();
    }

    /**
     * Does this category require credit_id?
     */
    public function requiresCreditId(): bool
    {
        return $this->isPaymentLinked();
    }

    /**
     * Can this category have payment_id?
     */
    public function allowsPaymentId(): bool
    {
        return $this->isPaymentLinked();
    }

    /**
     * Can this category have credit_id?
     */
    public function allowsCreditId(): bool
    {
        return $this->isPaymentLinked();
    }

    // ═══════════════════════════════════════════════════════════════════════
    // FINANCIAL IMPACT METHODS
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Does this income affect cash balance?
     * Most incomes affect cash, except some accounting adjustments.
     */
    public function affectsCash(): bool
    {
        // All income categories currently affect cash
        return true;
    }

    /**
     * Does this income affect working capital?
     *
     * TRUE for:
     * - Principal recovery (loan_payment_principal)
     * - Capital injections
     * - Opening balance
     *
     * FALSE for:
     * - Interest income (profit, not capital)
     * - Fees and penalties (profit, not capital)
     * - Overpayments (liability, not capital)
     */
    public function affectsCapital(): bool
    {
        return match ($this) {
            // Principal recovery increases available capital
            self::LOAN_PAYMENT_PRINCIPAL => true,

            // Capital transactions
            self::CAPITAL_INJECTION,
            self::PARTNER_CONTRIBUTION,
            self::INVESTOR_CONTRIBUTION,
            self::OPENING_BALANCE => true,

            // Legacy payment - conservative approach: affects capital
            self::PAYMENT => true,

            // Interest, fees, etc. are profit, not capital
            self::LOAN_PAYMENT_INTEREST,
            self::LATE_FEE,
            self::PENALTY_INTEREST,
            self::SERVICE_FEE,
            self::RECOVERY_BAD_DEBT,
            self::RECOVERY,
            self::EXTRA_CHARGE,
            self::OTHER_OPERATIONAL,
            self::OTHER_INCOME => false,

            // Overpayment is a liability, not capital or profit
            self::OVERPAYMENT => false,
        };
    }

    /**
     * Does this income affect profit (P&L)?
     *
     * TRUE for:
     * - Interest income
     * - Fees and penalties
     * - Bad debt recovery
     *
     * FALSE for:
     * - Principal recovery (capital, not profit)
     * - Capital injections (equity, not profit)
     * - Overpayments (liability, not profit)
     */
    public function affectsProfit(): bool
    {
        return match ($this) {
            // Interest is pure profit
            self::LOAN_PAYMENT_INTEREST => true,

            // Fees and penalties are profit
            self::LATE_FEE,
            self::PENALTY_INTEREST,
            self::SERVICE_FEE,
            self::EXTRA_CHARGE => true,

            // Bad debt recovery is profit (assuming was previously written off)
            self::RECOVERY_BAD_DEBT,
            self::RECOVERY => true,

            // Other operational income is profit
            self::OTHER_OPERATIONAL,
            self::OTHER_INCOME => true,

            // Legacy payment - conservative: assume it contains some interest
            self::PAYMENT => true,

            // Principal recovery is capital, not profit
            self::LOAN_PAYMENT_PRINCIPAL => false,

            // Capital transactions don't affect profit
            self::CAPITAL_INJECTION,
            self::PARTNER_CONTRIBUTION,
            self::INVESTOR_CONTRIBUTION,
            self::OPENING_BALANCE => false,

            // Overpayment is neither capital nor profit (liability)
            self::OVERPAYMENT => false,
        };
    }

    // ═══════════════════════════════════════════════════════════════════════
    // EDIT/DELETE PERMISSION METHODS
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Can this income record be edited?
     */
    public function canBeEdited(): bool
    {
        return match ($this) {
            // Payment-linked records are system-controlled
            self::PAYMENT,
            self::LOAN_PAYMENT_PRINCIPAL,
            self::LOAN_PAYMENT_INTEREST,
            self::OVERPAYMENT => false,

            // Opening balance is permanent
            self::OPENING_BALANCE => false,

            // Capital transactions: time-limited editing
            self::CAPITAL_INJECTION,
            self::PARTNER_CONTRIBUTION,
            self::INVESTOR_CONTRIBUTION => true, // Checked at service layer with time

            // Operational: can edit
            self::LATE_FEE,
            self::PENALTY_INTEREST,
            self::SERVICE_FEE,
            self::RECOVERY_BAD_DEBT,
            self::RECOVERY,
            self::EXTRA_CHARGE,
            self::OTHER_OPERATIONAL,
            self::OTHER_INCOME => true,
        };
    }

    /**
     * Can this income record be deleted?
     */
    public function canBeDeleted(): bool
    {
        return match ($this) {
            // Payment-linked records cannot be deleted
            self::PAYMENT,
            self::LOAN_PAYMENT_PRINCIPAL,
            self::LOAN_PAYMENT_INTEREST,
            self::OVERPAYMENT => false,

            // Opening balance is permanent
            self::OPENING_BALANCE => false,

            // Capital transactions: time-limited deletion
            self::CAPITAL_INJECTION,
            self::PARTNER_CONTRIBUTION,
            self::INVESTOR_CONTRIBUTION => false, // Should use compensating entry

            // Operational: can delete
            self::LATE_FEE,
            self::PENALTY_INTEREST,
            self::SERVICE_FEE,
            self::RECOVERY_BAD_DEBT,
            self::RECOVERY,
            self::EXTRA_CHARGE,
            self::OTHER_OPERATIONAL,
            self::OTHER_INCOME => true,
        };
    }

    /**
     * Does this category require approval above certain thresholds?
     */
    public function requiresApproval(): bool
    {
        return match ($this) {
            self::CAPITAL_INJECTION,
            self::INVESTOR_CONTRIBUTION,
            self::OPENING_BALANCE => true,
            default => false,
        };
    }

    // ═══════════════════════════════════════════════════════════════════════
    // UI DISPLAY METHODS
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * Human-readable label for UI.
     */
    public function getLabel(): string
    {
        return match ($this) {
            // Payment-linked
            self::PAYMENT => 'Pago de cliente',
            self::LOAN_PAYMENT_PRINCIPAL => 'Pago - Capital',
            self::LOAN_PAYMENT_INTEREST => 'Pago - Interés',
            self::OVERPAYMENT => 'Pago en exceso (saldo a favor)',

            // Capital
            self::CAPITAL_INJECTION => 'Inyección de capital',
            self::PARTNER_CONTRIBUTION => 'Aporte de socio',
            self::INVESTOR_CONTRIBUTION => 'Aporte de inversionista',
            self::OPENING_BALANCE => 'Balance inicial',

            // Operational
            self::LATE_FEE => 'Cargo por mora',
            self::PENALTY_INTEREST => 'Interés moratorio',
            self::SERVICE_FEE => 'Comisión por servicios',
            self::RECOVERY_BAD_DEBT => 'Recuperación de cartera castigada',
            self::RECOVERY => 'Recuperación',
            self::EXTRA_CHARGE => 'Cargo extra',
            self::OTHER_OPERATIONAL => 'Otro ingreso operativo',
            self::OTHER_INCOME => 'Otro ingreso',
        };
    }

    /**
     * Color for badges in UI.
     */
    public function getColor(): string
    {
        return match ($this) {
            // Payment-linked: shades of green
            self::PAYMENT => 'success',
            self::LOAN_PAYMENT_PRINCIPAL => 'success',
            self::LOAN_PAYMENT_INTEREST => 'emerald',
            self::OVERPAYMENT => 'info',

            // Capital: blue shades
            self::CAPITAL_INJECTION => 'primary',
            self::PARTNER_CONTRIBUTION => 'primary',
            self::INVESTOR_CONTRIBUTION => 'indigo',
            self::OPENING_BALANCE => 'slate',

            // Operational: various
            self::LATE_FEE => 'warning',
            self::PENALTY_INTEREST => 'orange',
            self::SERVICE_FEE => 'cyan',
            self::RECOVERY_BAD_DEBT => 'lime',
            self::RECOVERY => 'lime',
            self::EXTRA_CHARGE => 'amber',
            self::OTHER_OPERATIONAL => 'gray',
            self::OTHER_INCOME => 'gray',
        };
    }

    /**
     * Icon for UI display.
     */
    public function getIcon(): string
    {
        return match ($this) {
            self::PAYMENT,
            self::LOAN_PAYMENT_PRINCIPAL,
            self::LOAN_PAYMENT_INTEREST => 'heroicon-o-banknotes',
            self::OVERPAYMENT => 'heroicon-o-arrow-up-circle',

            self::CAPITAL_INJECTION,
            self::PARTNER_CONTRIBUTION,
            self::INVESTOR_CONTRIBUTION => 'heroicon-o-building-library',
            self::OPENING_BALANCE => 'heroicon-o-calendar',

            self::LATE_FEE,
            self::PENALTY_INTEREST => 'heroicon-o-clock',
            self::SERVICE_FEE => 'heroicon-o-document-currency-dollar',
            self::RECOVERY_BAD_DEBT,
            self::RECOVERY => 'heroicon-o-arrow-path',
            self::EXTRA_CHARGE => 'heroicon-o-plus-circle',
            self::OTHER_OPERATIONAL,
            self::OTHER_INCOME => 'heroicon-o-currency-dollar',
        };
    }

    /**
     * Detailed description for tooltips/help.
     */
    public function getDescription(): string
    {
        return match ($this) {
            self::PAYMENT => 'Pago de cliente (formato legacy, será migrado).',
            self::LOAN_PAYMENT_PRINCIPAL => 'Porción de capital recuperado del préstamo. Aumenta el capital disponible para prestar.',
            self::LOAN_PAYMENT_INTEREST => 'Porción de interés ganado del préstamo. Es la ganancia real del negocio.',
            self::OVERPAYMENT => 'Excedente pagado por el cliente. Genera un saldo a favor que puede aplicarse a futuras cuotas.',

            self::CAPITAL_INJECTION => 'Dinero aportado por el propietario para aumentar el capital de trabajo. NO es ganancia.',
            self::PARTNER_CONTRIBUTION => 'Aporte de socio (categoría legacy).',
            self::INVESTOR_CONTRIBUTION => 'Dinero aportado por un inversionista externo. Aumenta el capital pero NO las ganancias.',
            self::OPENING_BALANCE => 'Balance inicial al comenzar a usar el sistema. Solo puede registrarse una vez.',

            self::LATE_FEE => 'Cargo fijo por pago tardío. Es ingreso operativo (ganancia).',
            self::PENALTY_INTEREST => 'Interés adicional cobrado sobre montos vencidos. Es ingreso operativo (ganancia).',
            self::SERVICE_FEE => 'Comisión por servicios administrativos. Es ingreso operativo (ganancia).',
            self::RECOVERY_BAD_DEBT => 'Recuperación de dinero de créditos previamente castigados como incobrables.',
            self::RECOVERY => 'Recuperación (categoría legacy).',
            self::EXTRA_CHARGE => 'Cargo extra (categoría legacy).',
            self::OTHER_OPERATIONAL => 'Cualquier otro ingreso operativo no clasificado en las categorías anteriores.',
            self::OTHER_INCOME => 'Otro ingreso (categoría legacy).',
        };
    }

    /**
     * Financial impact summary for UI display.
     */
    public function getFinancialImpactSummary(): string
    {
        $impacts = [];

        if ($this->affectsCash()) {
            $impacts[] = '💵 Caja';
        }
        if ($this->affectsCapital()) {
            $impacts[] = '🏦 Capital';
        }
        if ($this->affectsProfit()) {
            $impacts[] = '📈 Utilidad';
        }

        return implode(' • ', $impacts) ?: 'Sin impacto directo';
    }

    // ═══════════════════════════════════════════════════════════════════════
    // OPTION ARRAYS FOR UI
    // ═══════════════════════════════════════════════════════════════════════

    /**
     * All category values as array.
     */
    public static function values(): array
    {
        return array_column(self::cases(), 'value');
    }

    /**
     * Options for manual creation in UI (excludes payment-linked and legacy).
     */
    public static function manualOptions(): array
    {
        $options = [];
        foreach (self::manualCreationCategories() as $category) {
            $options[$category->value] = $category->getLabel();
        }

        return $options;
    }

    /**
     * Options grouped by type for better UI organization.
     */
    public static function groupedOptions(): array
    {
        return [
            'Capital' => [
                self::CAPITAL_INJECTION->value => self::CAPITAL_INJECTION->getLabel(),
                self::INVESTOR_CONTRIBUTION->value => self::INVESTOR_CONTRIBUTION->getLabel(),
                self::OPENING_BALANCE->value => self::OPENING_BALANCE->getLabel(),
            ],
            'Ingresos Operativos' => [
                self::LATE_FEE->value => self::LATE_FEE->getLabel(),
                self::PENALTY_INTEREST->value => self::PENALTY_INTEREST->getLabel(),
                self::SERVICE_FEE->value => self::SERVICE_FEE->getLabel(),
                self::RECOVERY_BAD_DEBT->value => self::RECOVERY_BAD_DEBT->getLabel(),
                self::OTHER_OPERATIONAL->value => self::OTHER_OPERATIONAL->getLabel(),
            ],
        ];
    }

    /**
     * All options for administrative views (includes legacy).
     */
    public static function allOptions(): array
    {
        $options = [];
        foreach (self::cases() as $category) {
            $options[$category->value] = $category->getLabel();
        }

        return $options;
    }

    /**
     * Options for operational categories only (legacy backward compatibility).
     *
     * @deprecated Use manualOptions() instead
     */
    public static function operationalOptions(): array
    {
        return self::manualOptions();
    }
}
