import logging
from datetime import datetime, date
from typing import List, Dict, Any, Optional
import sys
import os
import paramiko
from fastapi import UploadFile
from dotenv import load_dotenv


from cnxpdo import get_connection

# Cargar variables de entorno
script_dir = os.path.dirname(os.path.abspath(__file__))
crm_dir = os.path.dirname(script_dir)
env_path = os.path.join(crm_dir, "configuraciones", ".env")
load_dotenv(env_path)

    # server = os.getenv('ftp_server')
    # username = os.getenv('ftp_user_name')
    # #pem_key_path = os.getenv('ftp_private_key_path')
    # passVal = os.getenv('ftp_user_pass')
    # port = int(os.getenv('ftp_port'))
    # ftp_path_imgs = os.getenv('ftp_path_imgs')

def obtener_noticiascrm(fecha: Optional[str]) -> Dict[str, Any]:
    conexion = None
    cursor = None

    try:
        conexion = get_connection()
        if not conexion:
            raise Exception("No se pudo establecer conexión a la base de datos")

        # Validación de la fecha
        if fecha:
            try:
                datetime.strptime(fecha, "%Y-%m-%d")
            except ValueError:
                raise ValueError("Formato de fecha inválido. Use YYYY-MM-DD")

        # Construcción del query - CAMBIO: fecha -> fecha_noticia
        query = """
            SELECT n.*, en.estado  
            FROM noticias n
            LEFT JOIN estado_noticias en ON n.id_estado = en.id
        """
        params = []

        if fecha:
            # CAMBIO: fecha -> fecha_noticia
            query += " WHERE DATE(fecha_noticia) = STR_TO_DATE(%s, '%%Y-%%m-%%d')"
            params.append(fecha)

        # Ordenar por fecha descendente - CAMBIO: fecha -> fecha_noticia
        query += " ORDER BY fecha_publicacion DESC"

        # Ejecutar consulta
        cursor = conexion.cursor(dictionary=True)
        cursor.execute(query, params)
        datos = cursor.fetchall()

        # Formatear fecha como string - CAMBIO: fecha -> fecha_noticia
        for noticia in datos:
            if isinstance(noticia["fecha_noticia"], (datetime, date)):
                noticia["fecha_noticia"] = noticia["fecha_noticia"].strftime("%Y-%m-%d")

        return {
            'success': 1,
            'message': 'Noticias encontradas',
            "data": datos
        }

    except Exception as e:
        logging.error(f"[ERROR] en obtener_noticias: {str(e)}")
        raise
    finally:
        if cursor:
            cursor.close()
        if conexion:
            conexion.close()

def insertar_noticia(datos: Dict[str, Any]) -> Dict[str, Any]:
    conexion = None
    cursor = None

    try:
        conexion = get_connection()
        if not conexion:
            raise Exception("No se pudo establecer conexión a la base de datos")

        # Validación de campos requeridos
        campos_requeridos = ['principal', 'fecha_noticia', 'titulo', 'link', 'texto_corto', 'texto_largo', 'id_estado', 'adjunto']
        for campo in campos_requeridos:
            if campo not in datos or datos[campo] is None or datos[campo] == '':
                raise ValueError(f"El campo '{campo}' es requerido")

        # Validación de la fecha
        try:
            datetime.strptime(datos['fecha_noticia'], "%Y-%m-%d")
        except ValueError:
            raise ValueError("Formato de fecha inválido. Use YYYY-MM-DD")
        
        archivo = datos['adjunto']

        try:
            archivo.file.seek(0)
            file_content = archivo.file.read()
            if not file_content:
                raise ValueError("El archivo está vacío o no se pudo leer.")
        except Exception as e:
            raise ValueError(f"Error al leer el archivo: {e}")

        # Configuración SFTP
        server = os.getenv('ftp_server')
        username = os.getenv('ftp_user_name')
        passVal = os.getenv('ftp_user_pass')
        port = 22
        ftp_path_imgs = os.getenv('ftp_path_imgs')
            
        print(f"🔍 [DEBUG] Variables de entorno SFTP:")
        print(f"   - Server new: {'✅ OK' if server else '❌ VACÍO'} ({server})")
        print(f"   - Username new: {'✅ OK' if username else '❌ VACÍO'} ({username})")
        print(f"   - PEM Key Path new: {'✅ OK' if passVal else '❌ VACÍO'} ({passVal})")
        print(f"   - Remote Folder new: {'✅ OK' if ftp_path_imgs else '❌ VACÍO'} ({ftp_path_imgs})")
        
        file_name = archivo.filename
        remote_file_path = f"{ftp_path_imgs}/{file_name}"

        transport = None
        sftp = None

        try:
            print(f"🔐 [SFTP] Subiendo imagen de noticia: {file_name}")
            transport = paramiko.Transport((server, port))
            transport.connect(username=username, password=passVal)
            sftp = paramiko.SFTPClient.from_transport(transport)

            # Subir archivo
            with sftp.file(remote_file_path, 'wb') as remote_file:
                remote_file.write(file_content)
                remote_file.flush()
            
            print(f"✅ Imagen subida correctamente: {remote_file_path}")
            imagen_path = file_name

        except Exception as e:
            raise Exception(f"Error al subir el archivo al servidor: {e}")
        finally:
            if sftp:
                sftp.close()
            if transport:
                transport.close()

        # Query de inserción
        query = """
            INSERT INTO noticias (principal, fecha_noticia, titulo, link, texto_corto, texto_largo, id_estado, imagen, fecha_publicacion)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, NOW())
        """
        
        # Parámetros para la inserción
        params = [
            datos['principal'],
            datos['fecha_noticia'],
            datos['titulo'],
            datos['link'],
            datos['texto_corto'],
            datos['texto_largo'],
            datos['id_estado'],
            imagen_path 
        ]

        # Ejecutar inserción
        cursor = conexion.cursor()
        cursor.execute(query, params)
        
        # Obtener el ID del registro insertado
        noticia_id = cursor.lastrowid
        
        # **NUEVA LÓGICA: Gestionar noticia principal**
        gestionar_noticia_principal(conexion, noticia_id, datos['principal'])
        
        # Confirmar todas las transacciones
        conexion.commit()

        return {
            'success': 1,
            'message': 'Noticia insertada correctamente',
            'data': {
                'id': noticia_id,
                'insertado': True
            }
        }

    except Exception as e:
        if conexion:
            conexion.rollback()
        logging.error(f"[ERROR] en insertar_noticia: {str(e)}")
        return {
            'success': 0,
            'message': f'Error al insertar noticia archivo not: {str(e)}',
            'data': None
        }
    finally:
        if cursor:
            cursor.close()
        if conexion:
            conexion.close()
            
            

def actualizar_noticia(id: int, datos: Dict[str, Any]) -> Dict[str, Any]:
    conexion = None
    cursor = None

    try:
        conexion = get_connection()
        if not conexion:
            raise Exception("No se pudo establecer conexión a la base de datos")

        # Validación de campos requeridos (sin incluir adjunto porque es opcional)
        campos_requeridos = ['principal', 'fecha_noticia', 'titulo', 'link', 'texto_corto', 'texto_largo', 'id_estado']
        for campo in campos_requeridos:
            if campo not in datos or datos[campo] is None or datos[campo] == '':
                raise ValueError(f"El campo '{campo}' es requerido")

        # Validación de la fecha
        try:
            datetime.strptime(datos['fecha_noticia'], "%Y-%m-%d")
        except ValueError:
            raise ValueError("Formato de fecha inválido. Use YYYY-MM-DD")
        
        # Obtener la imagen actual antes de procesar
        cursor_temp = conexion.cursor()
        cursor_temp.execute("SELECT imagen FROM noticias WHERE id = %s", (id,))
        resultado = cursor_temp.fetchone()
        cursor_temp.close()
        
        imagen_anterior = resultado[0] if resultado and resultado[0] else None
        
        archivo = datos.get('adjunto')  # UploadFile o None
        imagen_path = imagen_anterior  # Por defecto, mantener la imagen actual

        # Si se proporciona un archivo, procesarlo
        if archivo is not None and archivo.filename:
            try:
                archivo.file.seek(0)
                file_content = archivo.file.read()
                if not file_content:
                    raise ValueError("El archivo está vacío.")
                archivo.file.seek(0)
                
            except Exception as e:
                raise ValueError(f"Error al leer el archivo: {e}")

            # Configuración SFTP
            server = os.getenv('ftp_server')
            username = os.getenv('ftp_user_name')
            passVal = os.getenv('ftp_user_pass')
            port = 22
            ftp_path_imgs = os.getenv('ftp_path_imgs')
            
            file_name = archivo.filename
            remote_file_path = f"{ftp_path_imgs}/{file_name}"

            transport = None
            sftp = None

            try:
                # Conectar al servidor SFTP
                transport = paramiko.Transport((server, port))
                transport.connect(username=username, password=passVal)
                sftp = paramiko.SFTPClient.from_transport(transport)

                # Eliminar imagen anterior si existe y es diferente a la nueva
                if imagen_anterior and imagen_anterior != file_name:
                    try:
                        remote_old_path = f"{ftp_path_imgs}/{imagen_anterior}"
                        sftp.remove(remote_old_path)
                        logging.info(f"Imagen anterior eliminada: {imagen_anterior}")
                    except FileNotFoundError:
                        logging.warning(f"La imagen anterior no se encontró en el servidor: {imagen_anterior}")
                    except Exception as e:
                        logging.warning(f"Error al eliminar imagen anterior: {e}")

                # Subir nueva imagen
                with sftp.file(remote_file_path, 'wb') as remote_file:
                    remote_file.write(file_content)
                    remote_file.flush()
                
                imagen_path = file_name
                logging.info(f"Nueva imagen subida: {file_name}")

            except Exception as e:
                raise Exception(f"Error al subir el archivo al servidor: {e}")
            finally:
                if sftp:
                    sftp.close()
                if transport:
                    transport.close()

        # Query de actualización
        query = """
            UPDATE noticias
            SET principal = %s, fecha_noticia = %s, titulo = %s, link = %s,
                texto_corto = %s, texto_largo = %s, id_estado = %s, imagen = %s
            WHERE id = %s
        """

        # Parámetros para la actualización
        params = [
            datos['principal'],
            datos['fecha_noticia'],
            datos['titulo'],
            datos['link'],
            datos['texto_corto'],
            datos['texto_largo'],
            datos['id_estado'],
            imagen_path,
            id
        ]

        # Ejecutar actualización
        cursor = conexion.cursor()
        cursor.execute(query, params)

        # Verificar si se actualizó algún registro
        if cursor.rowcount == 0:
            raise ValueError("No se encontró la noticia para actualizar")

        # **NUEVA LÓGICA: Gestionar noticia principal**
        gestionar_noticia_principal(conexion, id, datos['principal'])
        
        # Confirmar todas las transacciones
        conexion.commit()

        return {
            'success': 1,
            'message': 'Noticia actualizada correctamente',
            'data': {
                'id': id,
                'insertado': True,
                'imagen': imagen_path if imagen_path else None,
                'url': f"{os.getenv('ftp_path_imgs')}/{imagen_path}" if imagen_path else None
            }
        }

    except Exception as e:
        if conexion:
            conexion.rollback()
        logging.error(f"[ERROR] en actualizar_noticia: {str(e)}")
        return {
            'success': 0,
            'message': f'Error al actualizar noticia: {str(e)}',
            'data': None
        }
    finally:
        if cursor:
            cursor.close()
        if conexion:
            conexion.close()
            
            
            
            
            
def eliminarNoticia(id_noticia):
    conexionBD = None
    cursor = None
    
    try:
        conexionBD = get_connection()
        if conexionBD is None:
            return {"success": False, "message": "Error de conexión"}
        
        cursor = conexionBD.cursor()
        
        # Primero obtener la información de la imagen antes de eliminar el registro
        query_select = "SELECT imagen FROM noticias WHERE id = %s"
        cursor.execute(query_select, (id_noticia,))
        resultado = cursor.fetchone()
        
        if not resultado:
            return {"success": False, "message": "Noticia no encontrada"}
        
        imagen_nombre = resultado[0] if resultado[0] else None
        
        # Eliminar imagen del servidor SFTP si existe
        if imagen_nombre:
            try:
                # Configuración SFTP
                server = os.getenv('ftp_server')
                username = os.getenv('ftp_user_name')
                passVal = os.getenv('ftp_user_pass')
                port = 22
                ftp_path_imgs = os.getenv('ftp_path_imgs')
                
                remote_file_path = f"{ftp_path_imgs}/{imagen_nombre}"
                
                transport = None
                sftp = None
                
                try:
                    # Conectar al servidor SFTP
                    transport = paramiko.Transport((server, port))
                    transport.connect(username=username, password=passVal)
                    sftp = paramiko.SFTPClient.from_transport(transport)
                    
                    # Eliminar archivo del servidor
                    sftp.remove(remote_file_path)
                    logging.info(f"Imagen eliminada del servidor: {imagen_nombre}")
                    
                except FileNotFoundError:
                    logging.warning(f"La imagen no se encontró en el servidor: {imagen_nombre}")
                    # Continuamos con la eliminación del registro aunque la imagen no exista
                except Exception as e:
                    logging.warning(f"Error al eliminar imagen del servidor: {e}")
                    # Continuamos con la eliminación del registro aunque falle la eliminación de la imagen
                finally:
                    if sftp:
                        sftp.close()
                    if transport:
                        transport.close()
                        
            except Exception as e:
                logging.error(f"Error en conexión SFTP: {e}")
                # Continuamos con la eliminación del registro
        
        # Eliminar registro de la base de datos
        query_delete = "DELETE FROM noticias WHERE id = %s"
        cursor.execute(query_delete, (id_noticia,))
        conexionBD.commit()
        
        if cursor.rowcount > 0:
            return {"success": True, "message": "Noticia e imagen eliminadas correctamente"}
        else:
            return {"success": False, "message": "Error al eliminar la noticia"}
        
    except Exception as e:
        if conexionBD:
            conexionBD.rollback()
        logging.error(f"[ERROR] en eliminarNoticia: {str(e)}")
        return {"success": False, "message": f"Error: {str(e)}"}
    
    finally:
        if cursor:
            cursor.close()
        if conexionBD:
            conexionBD.close()


def gestionar_noticia_principal(conexion, nueva_noticia_id: int, es_principal: int) -> None:

    cursor = None
    try:
        cursor = conexion.cursor()
        
        if es_principal == 1:
            # Desactivar todas las noticias principales excepto la actual
            query_desactivar = """
                UPDATE noticias 
                SET principal = 0 
                WHERE principal = 1 AND id != %s
            """
            cursor.execute(query_desactivar, (nueva_noticia_id,))
            
            filas_afectadas = cursor.rowcount
            if filas_afectadas > 0:
                logging.info(f"Se desactivaron {filas_afectadas} noticias principales anteriores")
        
    except Exception as e:
        logging.error(f"Error en gestionar_noticia_principal: {str(e)}")
        raise
    finally:
        if cursor:
            cursor.close()

