<?php
/**
 * NEXUS IT - DepreciacionController
 * Cálculo y gestión de depreciación de activos
 */
class DepreciacionController {

    /**
     * GET /depreciacion — Listar activos con su depreciación
     */
    public static function index(): void {
        $payload = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($payload);
        $db = getDB();

        $stmt = $db->query("SELECT a.id, a.codigo_activo, a.tipo, a.marca, a.modelo, a.fecha_compra, a.costo_adquisicion,
            d.metodo, d.vida_util_meses, d.valor_residual, d.depreciacion_mensual, d.valor_actual, d.ultimo_calculo
            FROM activos a
            LEFT JOIN depreciacion d ON a.id = d.activo_id
            WHERE a.costo_adquisicion > 0 AND a.estado != 'baja'
            ORDER BY a.costo_adquisicion DESC");
        Response::success($stmt->fetchAll());
    }

    /**
     * POST /depreciacion/:id/calcular — Configurar y calcular depreciación de un activo
     */
    public static function calcular(int $activoId): void {
        $payload = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($payload);
        $db = getDB();
        $body = Validator::getBody();

        // Get activo
        $activo = $db->prepare("SELECT id, costo_adquisicion, fecha_compra FROM activos WHERE id = ?");
        $activo->execute([$activoId]);
        $activo = $activo->fetch();
        if (!$activo) Response::notFound('Activo no encontrado');

        $costo = (float)$activo['costo_adquisicion'];
        if ($costo <= 0) Response::error('El activo no tiene costo de adquisición');

        $metodo = $body['metodo'] ?? 'linea_recta';
        $vidaUtil = (int)($body['vida_util_meses'] ?? 36);
        $valorResidual = (float)($body['valor_residual'] ?? 0);

        // Calcular
        $depMensual = ($costo - $valorResidual) / max(1, $vidaUtil);

        // Meses transcurridos desde fecha_compra
        $mesesTranscurridos = 0;
        if ($activo['fecha_compra']) {
            $compra = new DateTime($activo['fecha_compra']);
            $hoy = new DateTime();
            $diff = $compra->diff($hoy);
            $mesesTranscurridos = ($diff->y * 12) + $diff->m;
        }

        $depAcumulada = min($mesesTranscurridos * $depMensual, $costo - $valorResidual);
        $valorActual = max($valorResidual, $costo - $depAcumulada);

        if ($metodo === 'acelerada') {
            // Método de doble saldo decreciente
            $tasa = 2.0 / max(1, $vidaUtil);
            $valorActual = $costo;
            for ($i = 0; $i < $mesesTranscurridos && $valorActual > $valorResidual; $i++) {
                $dep = $valorActual * $tasa;
                $valorActual = max($valorResidual, $valorActual - $dep);
            }
            $depMensual = $mesesTranscurridos > 0 ? ($costo - $valorActual) / $mesesTranscurridos : 0;
        }

        // Upsert depreciacion
        $exists = $db->prepare("SELECT id FROM depreciacion WHERE activo_id = ?");
        $exists->execute([$activoId]);
        if ($exists->fetch()) {
            $db->prepare("UPDATE depreciacion SET metodo=?, vida_util_meses=?, valor_residual=?, depreciacion_mensual=?, valor_actual=?, ultimo_calculo=CURDATE() WHERE activo_id=?")
                ->execute([$metodo, $vidaUtil, $valorResidual, round($depMensual, 2), round($valorActual, 2), $activoId]);
        } else {
            $db->prepare("INSERT INTO depreciacion (activo_id, metodo, vida_util_meses, valor_residual, depreciacion_mensual, valor_actual, ultimo_calculo) VALUES (?,?,?,?,?,?,CURDATE())")
                ->execute([$activoId, $metodo, $vidaUtil, $valorResidual, round($depMensual, 2), round($valorActual, 2)]);
        }

        Response::success([
            'activo_id' => $activoId,
            'costo_original' => $costo,
            'metodo' => $metodo,
            'vida_util_meses' => $vidaUtil,
            'meses_transcurridos' => $mesesTranscurridos,
            'depreciacion_mensual' => round($depMensual, 2),
            'depreciacion_acumulada' => round($costo - $valorActual, 2),
            'valor_actual' => round($valorActual, 2),
            'porcentaje_depreciado' => round((($costo - $valorActual) / $costo) * 100, 1)
        ]);
    }

    /**
     * GET /depreciacion/resumen — Resumen general de depreciación
     */
    public static function resumen(): void {
        $payload = AuthMiddleware::verificar();
        RoleMiddleware::requireTecnico($payload);
        $db = getDB();

        $r = [];
        $r['valor_total_compra'] = (float)$db->query("SELECT COALESCE(SUM(costo_adquisicion),0) FROM activos WHERE estado != 'baja'")->fetchColumn();
        $r['valor_actual_total'] = (float)$db->query("SELECT COALESCE(SUM(d.valor_actual),0) FROM depreciacion d JOIN activos a ON d.activo_id = a.id WHERE a.estado != 'baja'")->fetchColumn();
        $r['depreciacion_total'] = $r['valor_total_compra'] - $r['valor_actual_total'];
        $r['activos_sin_calcular'] = (int)$db->query("SELECT COUNT(*) FROM activos a LEFT JOIN depreciacion d ON a.id = d.activo_id WHERE a.costo_adquisicion > 0 AND a.estado != 'baja' AND d.id IS NULL")->fetchColumn();
        $r['por_tipo'] = $db->query("SELECT a.tipo, COUNT(*) as cantidad, SUM(a.costo_adquisicion) as valor_compra, COALESCE(SUM(d.valor_actual), SUM(a.costo_adquisicion)) as valor_actual FROM activos a LEFT JOIN depreciacion d ON a.id = d.activo_id WHERE a.costo_adquisicion > 0 AND a.estado != 'baja' GROUP BY a.tipo ORDER BY valor_compra DESC")->fetchAll();

        Response::success($r);
    }
}
