from cnxpdo import get_connection
import logging
import traceback
from mysql.connector import Error as MySQLError
from datetime import datetime

def formatear_fecha_vencimiento(fecha_input):

    if not fecha_input:
        return None
    
    # Si ya viene en el formato correcto, la devolvemos tal como está
    if isinstance(fecha_input, str):
        try:
            # Intentar varios formatos comunes de fecha
            formatos_comunes = [
                '%Y-%m-%d',      # 2043-11-12
                '%d/%m/%Y',      # 12/11/2043
                '%m/%d/%Y',      # 11/12/2043
                '%d-%m-%Y',      # 12-11-2043
                '%m-%d-%Y',      # 11-12-2043
                '%Y/%m/%d',      # 2043/11/12
                '%d %m %Y',      # 12 11 2043
                '%Y%m%d'         # 20431112
            ]
            
            for formato in formatos_comunes:
                try:
                    fecha_obj = datetime.strptime(fecha_input, formato)
                    return fecha_obj.strftime('%Y-%m-%d')
                except ValueError:
                    continue
                    
        except Exception:
            pass
    
    # Si es un objeto datetime, formatearlo directamente
    elif isinstance(fecha_input, datetime):
        return fecha_input.strftime('%Y-%m-%d')
    
    # Si no se puede convertir, devolver la fecha original
    return fecha_input

def traer_lista_encuestas():
    # try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {
                "success": False,
                "message": "Error de conexión"
            }

        cursor = conexionBD.cursor(dictionary=True)
        query = """
            SELECT 
                e.id_enc, 
                e.nombre_encuesta, 
                ec.categoria as categoria, 
                e.fecha_vencimiento, e.status,  
                CONCAT(emp.nombres, ' ', emp.apellidos) AS usuario,
                e.fecha_creacion,
                e.descripcion
            FROM encuestas e
            LEFT JOIN encuestas_categorias ec  ON  e.categoria =  ec.id_enc_cat 
            LEFT JOIN usuarios u ON e.usuario = u.id
            LEFT JOIN empleados emp ON emp.id  = u.idEmpleado
            ORDER BY e.id_enc DESC
        """

        cursor.execute(query)
        encuestas = cursor.fetchall()


        cursor.close()
        conexionBD.close()
        return {
            "success": True,
            "message": "Encuestas obtenidas correctamente",
            "data": encuestas
        }
    # except Exception as e:
    #     return {
    #         "success": False,
    #         "message": f"Error: {str(e)}"
    #     }
    
def traer_lista_preguntas(id_enc: int):
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {
                "success": False,
                "message": "Error de conexión"
            }

        cursor = conexionBD.cursor(dictionary=True)
        query = """
            SELECT 
                ed.*,
                etp.tipo_pregunta as nombre_tipo_preg 
            FROM  encuestas_detalle ed 
            LEFT JOIN encuestas_tipos_preg etp ON ed.tipo_pregunta =  etp.id_enc_tipo_preg
            WHERE id_enc = %s AND ed.tipo_pregunta NOT IN (1, 2, 3)
            ORDER BY ed.id_enc_det DESC 
        """

        cursor.execute(query,(id_enc,))
        preguntas = cursor.fetchall()


        cursor.close()
        conexionBD.close()
        return {
            "success": True,
            "message": "Preguntas obtenidas correctamente",
            "data": preguntas
        }
    except Exception as e:
        return {
            "success": False,
            "message": f"Error: {str(e)}"
        }
    
def traer_lista_respuestas(id_enc_det: int):
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {
                "success": False,
                "message": "Error de conexión"
            }

        cursor = conexionBD.cursor(dictionary=True)
        query = """
            SELECT * FROM  encuestas_respuestas_pregunta  
            WHERE id_enc_det = %s
            ORDER BY id_enc_res_preg DESC
        """

        cursor.execute(query,(id_enc_det,))
        respuestas = cursor.fetchall()


        cursor.close()
        conexionBD.close()
        return {
            "success": True,
            "message": "Respuestas obtenidas correctamente",
            "data": respuestas
        }
    except Exception as e:
        return {
            "success": False,
            "message": f"Error: {str(e)}"
        }

def traer_tipos_preguntas():
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {
                "success": False,
                "message": "Error de conexión"
            }

        cursor = conexionBD.cursor(dictionary=True)
        query = " SELECT * FROM encuestas_tipos_preg"
        cursor.execute(query)
        tipos_pregutas = cursor.fetchall()


        cursor.close()
        conexionBD.close()
        return {
            "success": True,
            "message": "tablas obtenidas correctamente",
            "data": tipos_pregutas
        }
    except Exception as e:
        return {
            "success": False,
            "message": f"Error: {str(e)}"
        }
    
def traer_categorias_encuestas():
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {
                "success": False,
                "message": "Error de conexión"
            }

        cursor = conexionBD.cursor(dictionary=True)
        query = " SELECT * FROM encuestas_categorias"
        cursor.execute(query)
        tipos_pregutas = cursor.fetchall()


        cursor.close()
        conexionBD.close()
        return {
            "success": True,
            "message": "tablas obtenidas correctamente",
            "data": tipos_pregutas
        }
    except Exception as e:
        return {
            "success": False,
            "message": f"Error: {str(e)}"
        }
    
def insertar_pregunta(data):
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {"success": False, "message": "Error de conexión"}
        
        query = """
            INSERT INTO encuestas_detalle (id_enc, pregunta, tipo_pregunta, obligatorio) 
            VALUES (%s, %s, %s,%s)
        """
        
        cursor = conexionBD.cursor()
        cursor.execute(query, (
            data["id_enc"],
            data["pregunta"],
            data["tipo_pregunta"],
            data["obligatorio"]
        ))

        # Obtener el ID del último registro insertado
        last_id = cursor.lastrowid

        data["id_enc_det"] = last_id
        
        # Commit para confirmar la inserción
        conexionBD.commit()

        cursor.close()
        conexionBD.close()

        return {"success": True, "message": "Pregunta insertada correctamente", "data": data}
    
    except Exception as e:
        return {"success": False, "message": f"Error al insertar datos: {str(e)}"}

def insertar_encuesta(data):
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {"success": False, "message": "Error de conexión"}
        
        # Formatear la fecha de vencimiento si está presente
        fecha_vencimiento_formateada = None
        if "fecha_vencimiento" in data and data["fecha_vencimiento"]:
            fecha_vencimiento_formateada = formatear_fecha_vencimiento(data["fecha_vencimiento"])
        
        query = """
            INSERT INTO encuestas (nombre_encuesta, categoria, fecha_vencimiento, status,usuario, fecha_creacion, descripcion) 
            VALUES (%s, %s, %s,%s,%s, NOW(), %s)
        """
        
        cursor = conexionBD.cursor()
        cursor.execute(query, (
            data["nombre_encuesta"], 
            data["categoria"], 
            fecha_vencimiento_formateada, 
            data["status"], 
            data["usuario"],
            data["descripcion"]
        ))
        
         # Obtener el ID del último registro insertado
        last_id = cursor.lastrowid

        # guardar en data el ID insertado
        data["id_enc"] = last_id
        
        # Insertar las 3 preguntas por defecto en encuestas_detalle
        preguntas_default = [
            ("Ingresar numero documento", 1, 1),  # tipo_pregunta = 1, obligatorio = 1
            ("Ingresar tipo documento", 2, 1),    # tipo_pregunta = 2, obligatorio = 1
            ("Ingresar nombre del ciudadano", 3, 1)  # tipo_pregunta = 3, obligatorio = 1
        ]
        
        query_preguntas = """
            INSERT INTO encuestas_detalle (id_enc, pregunta, tipo_pregunta, obligatorio) 
            VALUES (%s, %s, %s, %s)
        """
        
        for pregunta, tipo_pregunta, obligatorio in preguntas_default:
            cursor.execute(query_preguntas, (last_id, pregunta, tipo_pregunta, obligatorio))
                
        # Commit para confirmar la inserción
        conexionBD.commit()

        # No es necesario hacer un fetchAll porque estamos insertando datos, pero podemos devolver la data
        cursor.close()
        conexionBD.close()

        return {"success": True, "message": "Encuesta y preguntas por defecto insertadas correctamente", "data": data}
    
    except Exception as e:
        return {"success": False, "message": f"Error al insertar datos: {str(e)}"}
    
def insertar_respuesta(data):
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {"success": False, "message": "Error de conexión"}
        
        query = """
            INSERT INTO encuestas_respuestas_pregunta (id_enc_det, respuesta_pregunta) 
            VALUES (%s, %s)
        """
        
        cursor = conexionBD.cursor()
        cursor.execute(query, (
            data["id_enc_det"], 
            data["respuesta_pregunta"]
        ))
        
         # Obtener el ID del último registro insertado
        last_id = cursor.lastrowid

        # guardar en data el ID insertado
        data["id_enc_res_preg"] = last_id
                
        # Commit para confirmar la inserción
        conexionBD.commit()

        # No es necesario hacer un fetchAll porque estamos insertando datos, pero podemos devolver la data
        cursor.close()
        conexionBD.close()

        return {"success": True, "message": "Datos insertados correctamente", "data": data}
    
    except Exception as e:
        return {"success": False, "message": f"Error al insertar datos: {str(e)}"}


def actualizar_encuestas(id_enc: int, data:dict):
    conexionBD = get_connection()
    cursor = None 
    
    if conexionBD is None:
        return {"success": False, "message": "Error de conexión a la base de datos"}

    try:       
        cursor = conexionBD.cursor(dictionary=True)

        # Formatear la fecha de vencimiento si está presente
        fecha_vencimiento_formateada = None
        if "fecha_vencimiento" in data and data["fecha_vencimiento"]:
            fecha_vencimiento_formateada = formatear_fecha_vencimiento(data["fecha_vencimiento"])

        query = """
            UPDATE encuestas
            SET nombre_encuesta = %s, categoria = %s, fecha_vencimiento = %s, status = %s, descripcion = %s
            WHERE id_enc = %s;
        """
        
        cursor.execute(query, (
            data["nombre_encuesta"],
            data["categoria"],
            fecha_vencimiento_formateada,
            data["status"],
            data["descripcion"],
            id_enc))

        conexionBD.commit()

        cursor.close()
        conexionBD.close()

        return {"success": True, "message": "Voluntario actualizado", "data": data}
    
    except MySQLError as db_error:
        logging.error("Error en la base de datos al actualizar la encuesta: %s", str(db_error))
        logging.error(traceback.format_exc())
        conexionBD.rollback()  # Revertir cambios en caso de error
        return {
            "success": False,
            "message": f"Error en la base de datos: {str(db_error)}",
            "trace": traceback.format_exc()
        }
    except Exception as e:
        logging.error("Error inesperado al actualizar la encuesta: %s", str(e))
        logging.error(traceback.format_exc())
        conexionBD.rollback()  # Revertir cambios en caso de error
        return {
            "success": False,
            "message": f"Error inesperado: {str(e)}",
            "trace": traceback.format_exc()
        }
    finally:
        if cursor:
            cursor.close()
        if conexionBD:
            conexionBD.close()

def actualizar_pregunta(id_enc_det: int, data: dict):
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {"success": False, "message": "Error de conexión"}
        
        query = """
            UPDATE encuestas_detalle 
            SET pregunta = %s, tipo_pregunta = %s, obligatorio = %s
            WHERE id_enc_det = %s
        """
        
        cursor = conexionBD.cursor()
        cursor.execute(query, (
            data["pregunta"],
            data["tipo_pregunta"],
            data["obligatorio"],
            id_enc_det
        ))
        
        # Commit para confirmar la actualización
        conexionBD.commit()

        cursor.close()
        conexionBD.close()

        return {"success": True, "message": "Pregunta actualizada correctamente", "data": data}
    
    except Exception as e:
        return {"success": False, "message": f"Error al actualizar pregunta: {str(e)}"}

def actualizar_respuesta(id_enc_res_preg: int, data: dict):
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {"success": False, "message": "Error de conexión"}
        
        query = """
            UPDATE encuestas_respuestas_pregunta 
            SET respuesta_pregunta = %s
            WHERE id_enc_res_preg = %s
        """
        
        cursor = conexionBD.cursor()
        cursor.execute(query, (
            data["respuesta_pregunta"],
            id_enc_res_preg
        ))
        
        # Commit para confirmar la actualización
        conexionBD.commit()

        cursor.close()
        conexionBD.close()

        return {"success": True, "message": "Respuesta actualizada correctamente", "data": data}
    
    except Exception as e:
        return {"success": False, "message": f"Error al actualizar respuesta: {str(e)}"}

def eliminar_pregunta(id_enc_det):
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {"success": False, "message": "Error de conexión"}
        
        cursor = conexionBD.cursor()
        
        # Primero eliminar todas las respuestas asociadas a la pregunta
        query_respuestas = """
            DELETE FROM encuestas_respuestas_pregunta 
            WHERE id_enc_det = %s
        """
        
        cursor.execute(query_respuestas, (id_enc_det,))
        respuestas_eliminadas = cursor.rowcount
        
        # Luego eliminar la pregunta de encuestas_detalle
        query_pregunta = """
            DELETE FROM encuestas_detalle 
            WHERE id_enc_det = %s
        """
        
        cursor.execute(query_pregunta, (id_enc_det,))
        pregunta_eliminada = cursor.rowcount
        
        # Verificar si se eliminó la pregunta
        if pregunta_eliminada == 0:
            cursor.close()
            conexionBD.close()
            return {"success": False, "message": "No se encontró la pregunta a eliminar"}
        
        # Commit para confirmar la eliminación
        conexionBD.commit()

        cursor.close()
        conexionBD.close()

        return {
            "success": True, 
            "message": f"Pregunta eliminada correctamente. Se eliminaron {respuestas_eliminadas} respuestas asociadas.",
            "data": {
                "id_enc_det": id_enc_det,
                "respuestas_eliminadas": respuestas_eliminadas,
                "pregunta_eliminada": True
            }
        }
    
    except Exception as e:
        return {"success": False, "message": f"Error al eliminar pregunta: {str(e)}"}

def eliminar_respuesta(id_enc_res_preg):
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {"success": False, "message": "Error de conexión"}
        
        cursor = conexionBD.cursor()
        
        query = """
            DELETE FROM encuestas_respuestas_pregunta 
            WHERE id_enc_res_preg = %s
        """
        
        cursor.execute(query, (id_enc_res_preg,))
        respuestas_eliminadas = cursor.rowcount
        
        # Verificar si se eliminó la respuesta
        if respuestas_eliminadas == 0:
            cursor.close()
            conexionBD.close()
            return {"success": False, "message": "No se encontró la respuesta a eliminar"}
        
        # Commit para confirmar la eliminación
        conexionBD.commit()

        cursor.close()
        conexionBD.close()

        return {
            "success": True, 
            "message": f"Respuesta eliminada correctamente.",
            "data": {
                "id_enc_res_preg": id_enc_res_preg,
                "respuesta_eliminada": True
            }
        }
    
    except Exception as e:
        return {"success": False, "message": f"Error al eliminar respuesta: {str(e)}"}

def desactivar_encuestas_vencidas():
    """
    Función que desactiva automáticamente las encuestas que han llegado a su fecha de vencimiento
    cambiando el status a 0 en lugar de eliminarlas
    """
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {"success": False, "message": "Error de conexión"}
        
        cursor = conexionBD.cursor()
        
        # Obtener la fecha actual
        fecha_actual = datetime.now().date()
        
        # Primero consultar cuántas encuestas se van a desactivar
        query_consulta = """
            SELECT id_enc, nombre_encuesta, fecha_vencimiento 
            FROM encuestas 
            WHERE DATE(fecha_vencimiento) <= %s AND status = 1
        """
        
        cursor.execute(query_consulta, (fecha_actual,))
        encuestas_a_desactivar = cursor.fetchall()
        
        if not encuestas_a_desactivar:
            cursor.close()
            conexionBD.close()
            return {
                "success": True,
                "message": "No hay encuestas vencidas para desactivar",
                "data": {
                    "encuestas_desactivadas": 0,
                    "encuestas_afectadas": []
                }
            }
        
        # Actualizar el status a 0 para las encuestas vencidas
        query_update = """
            UPDATE encuestas 
            SET status = 0 
            WHERE DATE(fecha_vencimiento) <= %s AND status = 1
        """
        
        cursor.execute(query_update, (fecha_actual,))
        encuestas_desactivadas = cursor.rowcount
        
        # Commit para confirmar los cambios
        conexionBD.commit()
        
        cursor.close()
        conexionBD.close()
        
        # Preparar información de las encuestas desactivadas
        encuestas_info = []
        for encuesta in encuestas_a_desactivar:
            encuestas_info.append({
                "id_enc": encuesta[0],
                "nombre_encuesta": encuesta[1],
                "fecha_vencimiento": str(encuesta[2])
            })
        
        return {
            "success": True,
            "message": f"Se desactivaron {encuestas_desactivadas} encuestas vencidas correctamente",
            "data": {
                "encuestas_desactivadas": encuestas_desactivadas,
                "fecha_actual": str(fecha_actual),
                "encuestas_afectadas": encuestas_info
            }
        }
    
    except Exception as e:
        return {"success": False, "message": f"Error al desactivar encuestas vencidas: {str(e)}"}

def verificar_y_desactivar_encuesta_especifica(id_enc: int):
    """
    Función que verifica y desactiva una encuesta específica si ha vencido
    """
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {"success": False, "message": "Error de conexión"}
        
        cursor = conexionBD.cursor(dictionary=True)
        
        # Obtener la fecha actual
        fecha_actual = datetime.now().date()
        
        # Consultar la encuesta específica
        query_consulta = """
            SELECT id_enc, nombre_encuesta, fecha_vencimiento, status 
            FROM encuestas 
            WHERE id_enc = %s
        """
        
        cursor.execute(query_consulta, (id_enc,))
        encuesta = cursor.fetchone()
        
        if not encuesta:
            cursor.close()
            conexionBD.close()
            return {"success": False, "message": "Encuesta no encontrada"}
        
        # Verificar si la encuesta ya está desactivada
        if encuesta['status'] == 0:
            cursor.close()
            conexionBD.close()
            return {
                "success": True,
                "message": "La encuesta ya está desactivada",
                "data": {
                    "id_enc": id_enc,
                    "nombre_encuesta": encuesta['nombre_encuesta'],
                    "status_actual": 0,
                    "accion_realizada": "ninguna"
                }
            }
        
        # Verificar si la encuesta ha vencido
        fecha_vencimiento = encuesta['fecha_vencimiento']
        if isinstance(fecha_vencimiento, str):
            fecha_vencimiento = datetime.strptime(fecha_vencimiento, '%Y-%m-%d').date()
        elif hasattr(fecha_vencimiento, 'date'):
            fecha_vencimiento = fecha_vencimiento.date()
        
        if fecha_vencimiento <= fecha_actual:
            # Desactivar la encuesta
            query_update = """
                UPDATE encuestas 
                SET status = 0 
                WHERE id_enc = %s
            """
            
            cursor.execute(query_update, (id_enc,))
            conexionBD.commit()
            
            cursor.close()
            conexionBD.close()
            
            return {
                "success": True,
                "message": "Encuesta desactivada por vencimiento",
                "data": {
                    "id_enc": id_enc,
                    "nombre_encuesta": encuesta['nombre_encuesta'],
                    "fecha_vencimiento": str(fecha_vencimiento),
                    "fecha_actual": str(fecha_actual),
                    "status_anterior": 1,
                    "status_actual": 0,
                    "accion_realizada": "desactivada"
                }
            }
        else:
            cursor.close()
            conexionBD.close()
            return {
                "success": True,
                "message": "La encuesta aún no ha vencido",
                "data": {
                    "id_enc": id_enc,
                    "nombre_encuesta": encuesta['nombre_encuesta'],
                    "fecha_vencimiento": str(fecha_vencimiento),
                    "fecha_actual": str(fecha_actual),
                    "status_actual": encuesta['status'],
                    "accion_realizada": "ninguna"
                }
            }
    
    except Exception as e:
        return {"success": False, "message": f"Error al verificar encuesta: {str(e)}"}
