<?php
/**
 * SAC 2026 - MOTOR DE GENERACIÓN v31.0
 * SOPORTE PARA MONTOS NEGATIVOS (DEVOLUCIONES/CRÉDITOS)
 * GESTIÓN DE GASTOS ESPECIALES Y CONSUMO AUTOMÁTICO DE CRÉDITOS
 */
require_once 'config.php';

checkAccess(['admin', 'programmer', 'board']);

$data = $REQUEST_DATA;
if (!$data || !isset($data['id'])) response(["error" => "Datos de facturación insuficientes"], 400);

try {
    $pdo->beginTransaction();

    $feeId = $data['id'];
    $reservePct = (float)($data['reserveFundPercent'] ?? 10);
    $exchangeRate = (float)$data['exchangeRate'];
    
    // 1. Cabecera
    $stmt = $pdo->prepare("INSERT INTO monthly_fees 
        (id, month, year, exchange_rate, reserve_fund_percent, total_usd, total_bs, status, created_at) 
        VALUES (?, ?, ?, ?, ?, ?, ?, 'Generada', NOW())
        ON DUPLICATE KEY UPDATE exchange_rate=VALUES(exchange_rate), total_usd=VALUES(total_usd), total_bs=VALUES(total_bs)");
    $stmt->execute([$feeId, (int)$data['month'], (int)$data['year'], $exchangeRate, $reservePct, (float)$data['totalUsd'], (float)$data['totalBs']]);

    // 2. Limpiar items previos
    $pdo->prepare("DELETE FROM monthly_fee_items WHERE fee_id = ?")->execute([$feeId]);

    // 3. Registro de Gastos (MODIFICADO: Ahora permite montos negativos != 0)
    $itemStmt = $pdo->prepare("INSERT INTO monthly_fee_items (fee_id, category, description, amount_usd, is_uncommon, is_special, special_property_ids) VALUES (?, ?, ?, ?, ?, ?, ?)");
    $sections = [['fixed', $data['fixedExpenses'] ?? []], ['variable', $data['variableExpenses'] ?? []], ['other', $data['otherExpenses'] ?? []]];
    
    foreach ($sections as $section) {
        foreach ($section[1] as $item) {
            // CRÍTICO: Se eliminó (float)$item['amountUsd'] <= 0 para permitir devoluciones
            if (empty($item['description']) || (float)$item['amountUsd'] == 0) continue;
            
            $itemStmt->execute([
                $feeId, 
                $section[0], 
                $item['description'], 
                (float)$item['amountUsd'], 
                (isset($item['isUncommon']) && $item['isUncommon']) ? 1 : 0, 
                (isset($item['isSpecial']) && $item['isSpecial']) ? 1 : 0, 
                (isset($item['specialPropertyIds']) && is_array($item['specialPropertyIds'])) ? json_encode($item['specialPropertyIds']) : null
            ]);
        }
    }

    // 4. GENERACIÓN DE DEUDAS
    $props = $pdo->query("SELECT id, aliquot, has_uncommon, credit_balance, initial_debt FROM properties")->fetchAll();
    
    $totalAliquotUncommon = 0;
    foreach($props as $p) if($p['has_uncommon']) $totalAliquotUncommon += (float)$p['aliquot'];

    // Conteo absoluto de casas marcadas con Gasto No Común para distribución plana si aplica
    $stmtCountGNC = $pdo->query("SELECT COUNT(*) FROM properties WHERE has_uncommon = 1");
    $countGncTotal = (int)$stmtCountGNC->fetchColumn();

    $pdo->prepare("DELETE FROM property_debts WHERE fee_id = ?")->execute([$feeId]);
    $debtStmt = $pdo->prepare("INSERT INTO property_debts (fee_id, property_id, amount_usd, paid_amount, previous_debt, status) VALUES (?, ?, ?, ?, ?, ?)");

    foreach ($props as $p) {
        $propertyId = (int)$p['id'];
        $myAliquot = (float)$p['aliquot'];
        $cargoMesBase = 0;

        foreach ($sections as $section) {
            foreach ($section[1] as $item) {
                if (empty($item['description'])) continue;
                $montoItem = (float)$item['amountUsd'];
                
                if (isset($item['isSpecial']) && $item['isSpecial']) {
                    $selectedIds = $item['specialPropertyIds'] ?? [];
                    if (in_array($propertyId, $selectedIds)) {
                        // Distribución plana entre seleccionados
                        $cargoMesBase += ($montoItem / count($selectedIds));
                    }
                } 
                else if (isset($item['isUncommon']) && $item['isUncommon']) {
                    if ($p['has_uncommon'] && $countGncTotal > 0) {
                        // Distribución plana entre universo GNC
                        $cargoMesBase += ($montoItem / $countGncTotal);
                    }
                } 
                else {
                    // Alícuota ordinaria
                    $cargoMesBase += $montoItem * ($myAliquot / 100);
                }
            }
        }

        $montoConReserva = round($cargoMesBase * (1 + ($reservePct / 100)), 2);

        // Acarreo de deuda anterior real
        $carryQuery = $pdo->prepare("SELECT SUM(amount_usd - paid_amount) as saldo FROM property_debts WHERE property_id = ? AND status != 'Pagado' AND fee_id != ?");
        $carryQuery->execute([$propertyId, $feeId]);
        $previousDebt = round((float)$carryQuery->fetchColumn() + (float)$p['initial_debt'], 2);

        // CONSUMO DE SALDO A FAVOR (Solo si el cargo del mes es positivo)
        $creditAvailable = round((float)$p['credit_balance'], 2);
        $appliedPayment = 0;
        
        if ($montoConReserva > 0 && $creditAvailable > 0) {
            $appliedPayment = min($creditAvailable, $montoConReserva);
            $newCreditBalance = round($creditAvailable - $appliedPayment, 2);
            $pdo->prepare("UPDATE properties SET credit_balance = ? WHERE id = ?")->execute([$newCreditBalance, $propertyId]);
            $pdo->prepare("INSERT INTO credit_movements (property_id, fee_id, amount_usd, type, description) VALUES (?, ?, ?, 'Consumido', 'Aplicación automática de saldo a favor')")
                ->execute([$propertyId, $feeId, $appliedPayment]);
        }

        $status = ($appliedPayment >= ($montoConReserva - 0.01) && $montoConReserva > 0) ? 'Pagado' : ($appliedPayment > 0 ? 'Parcial' : 'Pendiente');
        // Si el monto es negativo, el estatus es 'Pagado' de facto ya que es un crédito
        if ($montoConReserva <= 0) $status = 'Pagado';

        $debtStmt->execute([$feeId, $propertyId, $montoConReserva, $appliedPayment, $previousDebt, $status]);
        
        if ($appliedPayment > 0) {
            $lastDebtId = $pdo->lastInsertId();
            $pdo->prepare("INSERT INTO payments (debt_id, amount_usd, method, reference, payment_date) VALUES (?, ?, 'Saldo a Favor', 'AUTO-APPLY', CURDATE())")
                ->execute([$lastDebtId, $appliedPayment]);
        }
    }

    $pdo->commit();
    logSystemAction("GENERÓ cuota $feeId soportando montos negativos para devoluciones.", "CUOTAS");
    response(["success" => true]);

} catch (Exception $e) {
    if ($pdo->inTransaction()) $pdo->rollBack();
    response(["error" => $e->getMessage()], 500);
}
?>