<?php

require_once "conexion.php";

class ModeloTransacciones {

    /*=============================================
    Conexión
    =============================================*/
    private $db;

    public function __construct() {
        $this->db = Conexion::conectar(); // Usamos tu clase Conexion
    }

    /*=============================================
    Obtener resumen de ingresos y gastos por mes
    =============================================*/
    public function getResumenMensual() {
        $sql = "SELECT 
                    DATE_FORMAT(fecha, '%Y-%m') AS mes,
                    SUM(CASE WHEN tt.tipo = 'ingreso' THEN t.monto ELSE 0 END) AS ingresos,
                    SUM(CASE WHEN tt.tipo = 'gasto' THEN t.monto ELSE 0 END) AS gastos
                FROM Transacciones t
                JOIN Tipo_Transaccion tt ON t.id_tipo_transaccion = tt.id_tipo_transaccion
                GROUP BY mes
                ORDER BY mes";
        $stmt = $this->db->prepare($sql);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

        /*=============================================
    INGRESAR TRANSACCIÓN
    =============================================*/
    static public function mdlIngresarTransaccion($tabla, $datos) {

        // Base del query
        $campos = "monto, fecha, descripcion, referencia, id_usuario, id_tipo_transaccion, metodo_pago";
        $valores = ":monto, :fecha, :descripcion, :referencia, :id_usuario, :id_tipo_transaccion, :metodo_pago";

        // Agregar campos opcionales si están presentes
        if (!empty($datos["id_venta"])) {
            $campos .= ", id_venta";
            $valores .= ", :id_venta";
        }

        if (!empty($datos["id_compra"])) {
            $campos .= ", id_compra";
            $valores .= ", :id_compra";
        }

        $stmt = Conexion::conectar()->prepare("INSERT INTO $tabla ($campos) VALUES ($valores)");

        // Bind obligatorios
        $stmt->bindParam(":monto", $datos["monto"], PDO::PARAM_STR);
        $stmt->bindParam(":fecha", $datos["fecha"], PDO::PARAM_STR);
        $stmt->bindParam(":descripcion", $datos["descripcion"], PDO::PARAM_STR);
        $stmt->bindParam(":referencia", $datos["referencia"], PDO::PARAM_STR);
        $stmt->bindParam(":id_usuario", $datos["id_usuario"], PDO::PARAM_INT);
        $stmt->bindParam(":id_tipo_transaccion", $datos["id_tipo_transaccion"], PDO::PARAM_INT);
        $stmt->bindParam(":metodo_pago", $datos["metodo_pago"], PDO::PARAM_STR);

        // Bind opcionales
        if (!empty($datos["id_venta"])) {
            $stmt->bindParam(":id_venta", $datos["id_venta"], PDO::PARAM_INT);
        }

        if (!empty($datos["id_compra"])) {
            $stmt->bindParam(":id_compra", $datos["id_compra"], PDO::PARAM_INT);
        }

        if ($stmt->execute()) {
            return "ok";
        } else {
            $errorInfo = $stmt->errorInfo();
            return "error: " . $errorInfo[2];
        }

        $stmt = null;
    }

    
        /*=============================================
    MOSTRAR TODAS LAS TRANSACCIONES
    =============================================*/
    static public function mdlMostrarTransacciones($tabla, $fechaInicio = null, $fechaFin = null, $tipoTransaccion = null) {

        $query = "
            SELECT 
                t.*, 
                tt.nombre, 
                tt.tipo 
            FROM $tabla t 
            INNER JOIN tipo_transaccion tt 
            ON t.id_tipo_transaccion = tt.id_tipo_transaccion 
            WHERE 1 = 1
        ";

        // Filtros opcionales
        if ($fechaInicio && $fechaFin) {
            $query .= " AND DATE(t.fecha) BETWEEN :fechaInicio AND :fechaFin";
        }

        if ($tipoTransaccion) {
            $query .= " AND tt.tipo = :tipoTransaccion";
        }

        $query .= " ORDER BY t.fecha DESC";

        $stmt = Conexion::conectar()->prepare($query);

        // Bind de parámetros
        if ($fechaInicio && $fechaFin) {
            $stmt->bindParam(":fechaInicio", $fechaInicio, PDO::PARAM_STR);
            $stmt->bindParam(":fechaFin", $fechaFin, PDO::PARAM_STR);
        }

        if ($tipoTransaccion) {
            $stmt->bindParam(":tipoTransaccion", $tipoTransaccion, PDO::PARAM_STR);
        }

        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }


        /*=============================================
    MOSTRAR TIPOS DE TRANSACCIÓN
    =============================================*/
    static public function mdlMostrarTiposTransaccion($tabla) {

        $stmt = Conexion::conectar()->prepare("SELECT * FROM $tabla ORDER BY nombre ASC");
        $stmt->execute();
        return $stmt->fetchAll();
    }
    
        static public function mdlMostrarUnaTransaccion($tabla, $id) {
        $stmt = Conexion::conectar()->prepare("SELECT * FROM $tabla WHERE id_transaccion = :id");
        $stmt->bindParam(":id", $id, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetch();
    }
    
        /*=============================================
    ELIMINAR TRANSACCIÓN
    =============================================*/
    static public function mdlEliminarTransaccion($tabla, $id) {

        $stmt = Conexion::conectar()->prepare("DELETE FROM $tabla WHERE id_transaccion = :id");
        $stmt->bindParam(":id", $id, PDO::PARAM_INT);

        if ($stmt->execute()) {
            return "ok";
        } else {
            return "error";
        }
    }
    
            /*=============================================
        EDITAR TRANSACCIÓN
        =============================================*/
        static public function mdlEditarTransacciones($tabla, $datos) {

            $stmt = Conexion::conectar()->prepare("UPDATE $tabla 
                SET monto = :monto, 
                    fecha = :fecha, 
                    descripcion = :descripcion, 
                    referencia = :referencia, 
                    metodo_pago = :metodo_pago, 
                    id_tipo_transaccion = :id_tipo_transaccion 
                WHERE id_transaccion = :id_transaccion");

            $stmt->bindParam(":id_transaccion", $datos["id_transaccion"], PDO::PARAM_INT);
            $stmt->bindParam(":monto", $datos["monto"], PDO::PARAM_STR);
            $stmt->bindParam(":fecha", $datos["fecha"], PDO::PARAM_STR);
            $stmt->bindParam(":descripcion", $datos["descripcion"], PDO::PARAM_STR);
            $stmt->bindParam(":referencia", $datos["referencia"], PDO::PARAM_STR);
            $stmt->bindParam(":metodo_pago", $datos["metodo_pago"], PDO::PARAM_STR);
            $stmt->bindParam(":id_tipo_transaccion", $datos["id_tipo_transaccion"], PDO::PARAM_INT);

            if ($stmt->execute()) {
                return "ok";
            } else {
                return "error";
            }

            $stmt = null;
        }

        static public function mdlObtenerTransaccionPorVenta($idVenta) {

            $stmt = Conexion::conectar()->prepare("SELECT id_transaccion FROM transacciones WHERE id_venta = :id_venta");
            $stmt->bindParam(":id_venta", $idVenta, PDO::PARAM_INT);

            $stmt->execute();
            return $stmt->fetch(PDO::FETCH_ASSOC); // Devuelve ['id_transaccion' => X]

            $stmt = null;
        }
        
        static public function mdlObtenerTransaccionPorCompra($idCompra) {

            $stmt = Conexion::conectar()->prepare("SELECT id_transaccion FROM transacciones WHERE id_compra = :id_compra");
            $stmt->bindParam(":id_compra", $idCompra, PDO::PARAM_INT);

            $stmt->execute();
            return $stmt->fetch(PDO::FETCH_ASSOC); // Devuelve ['id_transaccion' => X]

            $stmt = null;
        }


        static public function mdlEliminarTransaccionPorVenta($tabla, $idVenta) {
            $stmt = Conexion::conectar()->prepare("DELETE FROM $tabla WHERE id_venta = :idVenta");
            $stmt->bindParam(":idVenta", $idVenta, PDO::PARAM_INT);

            if ($stmt->execute()) {
                return "ok";
            } else {
                return "error";
            }
        }
        

    /*=============================================
    INGRESAR NUEVO TIPO DE TRANSACCIÓN
    =============================================*/
    static public function mdlIngresarTipoTransaccion($tabla, $datos) {

        // Modificamos la consulta SQL para incluir los tres campos: nombre, descripcion y tipo
        $stmt = Conexion::conectar()->prepare("INSERT INTO $tabla(nombre, descripcion, tipo) VALUES (:nombre, :descripcion, :tipo)");

        // Vinculamos los parámetros
        $stmt->bindParam(":nombre", $datos["nombre"], PDO::PARAM_STR);
        $stmt->bindParam(":descripcion", $datos["descripcion"], PDO::PARAM_STR);
        $stmt->bindParam(":tipo", $datos["tipo"], PDO::PARAM_STR);

        // Ejecutamos la consulta
        if ($stmt->execute()) {
            return "ok";  // Si la ejecución es exitosa
        } else {
            return "error";  // Si ocurre un error
        }

        // Cerramos la declaración
        $stmt = null;
    }


    /*=============================================
    EDITAR TIPO DE TRANSACCION
    =============================================*/
    static public function mdlEditarTipoTransaccion($tabla, $datos) {

        $stmt = Conexion::conectar()->prepare("UPDATE $tabla SET nombre = :nombre, descripcion = :descripcion, tipo = :tipo WHERE id_tipo_transaccion = :id");

        $stmt->bindParam(":nombre", $datos["nombre"], PDO::PARAM_STR);
        $stmt->bindParam(":descripcion", $datos["descripcion"], PDO::PARAM_STR);
        $stmt->bindParam(":tipo", $datos["tipo"], PDO::PARAM_STR); // 'ingreso' o 'gasto'
        $stmt->bindParam(":id", $datos["id"], PDO::PARAM_INT);

        if ($stmt->execute()) {
            return "ok";
        } else {
            return "error";
        }

        $stmt = null;
    }


    /*=============================================
    ELIMINAR TIPO DE TRANSACCION
    =============================================*/
    static public function mdlEliminarTipoTransaccion($tabla, $id) {
        // Verificar si el ID es válido (entero y mayor que 0)
        if (!is_numeric($id) || $id <= 0) {
            return "error: id inválido";
        }

        // Preparar la consulta SQL para eliminar el tipo de transacción
        try {
            $stmt = Conexion::conectar()->prepare("DELETE FROM $tabla WHERE id_tipo_transaccion = :id");

            // Vincular el parámetro ID con el valor
            $stmt->bindParam(":id", $id, PDO::PARAM_INT);

            // Ejecutar la consulta
            if ($stmt->execute()) {
                return "ok"; // Eliminado exitosamente
            } else {
                return "error: no se pudo eliminar"; // Error en la ejecución
            }
        } catch (PDOException $e) {
            // Capturar errores de la base de datos
            return "error: " . $e->getMessage();
        } finally {
            // Asegurarse de que el statement se cierre después de ejecutarse
            $stmt = null;
        }
    }

    
    static public function mdlMostrarUnTipoTransaccion($tabla, $id) {
        $stmt = Conexion::conectar()->prepare("SELECT * FROM $tabla WHERE id_tipo_transaccion = :id");
        $stmt->bindParam(":id", $id, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetch();
    }
    
    /*=============================================
    SECCION DE REPORTES MENSUAL POR AÑO
    =============================================*/
    
    static public function mdlReporteMensualPorAnio($tabla, $anio) {

        $query = "
            SELECT 
                DATE_FORMAT(t.fecha, '%Y-%m') AS mes,
                SUM(CASE WHEN tt.tipo = 'ingreso' THEN t.monto ELSE 0 END) AS total_ingresos,
                SUM(CASE WHEN tt.tipo = 'gasto' THEN t.monto ELSE 0 END) AS total_gastos,
                SUM(CASE 
                        WHEN tt.tipo = 'ingreso' THEN t.monto 
                        WHEN tt.tipo = 'gasto' THEN -t.monto 
                        ELSE 0 
                    END) AS balance_mensual
            FROM $tabla t
            INNER JOIN tipo_transaccion tt 
                ON t.id_tipo_transaccion = tt.id_tipo_transaccion
            WHERE YEAR(t.fecha) = :anio
            GROUP BY mes
            ORDER BY mes ASC
        ";

        $stmt = Conexion::conectar()->prepare($query);
        $stmt->bindParam(":anio", $anio, PDO::PARAM_INT);

        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

        static public function mdlResumenFinancieroAnual($tabla, $anio) {

        $query = "
            SELECT 
                SUM(CASE WHEN tt.tipo = 'ingreso' THEN t.monto ELSE 0 END) AS total_ingresos,
                SUM(CASE WHEN tt.tipo = 'gasto' THEN t.monto ELSE 0 END) AS total_gastos
            FROM $tabla t
            INNER JOIN tipo_transaccion tt 
                ON t.id_tipo_transaccion = tt.id_tipo_transaccion
            WHERE YEAR(t.fecha) = :anio
        ";

        $stmt = Conexion::conectar()->prepare($query);
        $stmt->bindParam(":anio", $anio, PDO::PARAM_INT);
        $stmt->execute();

        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    
    public static function mdlBalanceMensual($tabla, $anio) {
        // Consulta para obtener ingresos y gastos por mes
        $query = "
            SELECT 
                MONTH(t.fecha) AS mes,
                SUM(CASE WHEN tt.tipo = 'ingreso' THEN t.monto ELSE 0 END) AS total_ingresos,
                SUM(CASE WHEN tt.tipo = 'gasto' THEN t.monto ELSE 0 END) AS total_gastos
            FROM $tabla t
            INNER JOIN tipo_transaccion tt ON t.id_tipo_transaccion = tt.id_tipo_transaccion
            WHERE YEAR(t.fecha) = :anio
            GROUP BY MONTH(t.fecha)
            ORDER BY mes
        ";

        $stmt = Conexion::conectar()->prepare($query);
        $stmt->bindParam(":anio", $anio, PDO::PARAM_INT);
        $stmt->execute();

        $resultados = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // Asegurarnos de que haya datos para cada mes, incluso si hay meses sin ingresos/gastos
        $meses = [];
        for ($i = 1; $i <= 12; $i++) {
            // Inicializamos con 0 si no hay datos para ese mes
            $meses[$i] = [
                'mes' => $i,
                'total_ingresos' => 0,
                'total_gastos' => 0
            ];
        }

        // Rellenar los meses con los datos obtenidos
        foreach ($resultados as $res) {
            $meses[$res['mes']]['total_ingresos'] = $res['total_ingresos'];
            $meses[$res['mes']]['total_gastos'] = $res['total_gastos'];
        }

        return $meses;
    }

    static public function mdlObtenerResumenGastos($tabla, $anio, $mes) {
        $stmt = Conexion::conectar()->prepare("
            SELECT 
          SUM(CASE WHEN tt.nombre = 'Compras' THEN t.monto ELSE 0 END) AS compras,
          SUM(CASE WHEN tt.nombre != 'Compras' THEN t.monto ELSE 0 END) AS operativos
        FROM transacciones t
        INNER JOIN tipo_transaccion tt ON t.id_tipo_transaccion = tt.id_tipo_transaccion
        WHERE tt.tipo = 'gasto'
          AND YEAR(t.fecha) = :anio
          AND MONTH(t.fecha) = :mes
        ");

        $stmt->bindParam(":anio", $anio, PDO::PARAM_INT);
        $stmt->bindParam(":mes", $mes, PDO::PARAM_INT);
        $stmt->execute();

        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    
    static public function mdlDetalleGastosMensuales($tabla, $anio, $mes) {
        $stmt = Conexion::conectar()->prepare("
            SELECT 
                tt.nombre AS categoria,
                SUM(t.monto) AS total
            FROM $tabla t
            INNER JOIN tipo_transaccion tt ON t.id_tipo_transaccion = tt.id_tipo_transaccion
            WHERE tt.tipo = 'gasto' 
              AND YEAR(t.fecha) = :anio 
              AND MONTH(t.fecha) = :mes
            GROUP BY tt.nombre
            ORDER BY total DESC
        ");
        $stmt->bindParam(":anio", $anio, PDO::PARAM_INT);
        $stmt->bindParam(":mes", $mes, PDO::PARAM_INT);
        $stmt->execute();

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    // Función en el Modelo: mdlDetalleIngresos($anio, $mes)
    static public function mdlDetalleIngresos($anio, $mes) {
        $stmt = Conexion::conectar()->prepare("
            SELECT 
                DATE(t.fecha) AS fecha,
                SUM(t.monto) AS monto,
                tt.nombre AS categoria,
                t.descripcion
            FROM transacciones t
            INNER JOIN tipo_transaccion tt ON t.id_tipo_transaccion = tt.id_tipo_transaccion
            WHERE tt.tipo = 'ingreso'
              AND YEAR(t.fecha) = :anio 
              AND MONTH(t.fecha) = :mes
            GROUP BY DATE(t.fecha), tt.nombre
            ORDER BY fecha ASC;

        ");

        // Bind de parámetros
        $stmt->bindParam(":anio", $anio, PDO::PARAM_INT);
        $stmt->bindParam(":mes", $mes, PDO::PARAM_INT);

        // Ejecutamos la consulta
        $stmt->execute();

        // Devolvemos los resultados
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    // Función en el Modelo: mdlDetalleGastos($anio, $mes)
    static public function mdlDetalleGastos($anio, $mes) {
        $stmt = Conexion::conectar()->prepare("
            SELECT 
            DATE(t.fecha) AS fecha,
            SUM(t.monto) AS monto,
            tt.nombre AS categoria,
            t.descripcion
        FROM transacciones t
        INNER JOIN tipo_transaccion tt ON t.id_tipo_transaccion = tt.id_tipo_transaccion
        WHERE tt.tipo = 'gasto'
          AND YEAR(t.fecha) = :anio 
          AND MONTH(t.fecha) = :mes
        GROUP BY DATE(t.fecha), tt.nombre
        ORDER BY fecha ASC;

        ");

        // Bind de parámetros
        $stmt->bindParam(":anio", $anio, PDO::PARAM_INT);
        $stmt->bindParam(":mes", $mes, PDO::PARAM_INT);

        // Ejecutamos la consulta
        $stmt->execute();

        // Devolvemos los resultados
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }


}
