# Archivo: DocsManagementSQL.py
# Ruta: src/Consultas_SQL/Utilities/DocsManagementSQL.PY
# Descripción: Funciones SQL para gestión de documentos
# Autor: Equipo de Desarrollo IGSA
# Fecha: 2025

import pyodbc
import logging
from datetime import datetime
from typing import Dict, List, Optional

# Configurar logging
logger = logging.getLogger('docs_management_sql')

from config import Productivo
from Consultas_SQL.conexion import get_connection

def crear_docs_head(user_id: int, origen: str, created_by: str) -> Dict:
    """
    Crea un registro en Q_SpQ_DocsHead para agrupar documentos
    
    Args:
        user_id (int): ID del usuario
        origen (str): Módulo origen (ej: "Q_SpQ_FormsHead")
        created_by (str): Nombre completo del usuario
    
    Returns:
        Dict: Resultado con DocsID generado
    """
    
    query = """
        INSERT INTO Q_SpQ_DocsHead (
            Origen,
            UserID,
            CreatedBy
        ) VALUES (?, ?, ?)
    """

    conn = None
    try:
        conn = get_connection()
        if not conn:
            raise ConnectionError("No se pudo establecer conexión con la base de datos")
        
        with conn:
            cursor = conn.cursor()
            cursor.execute(query, (origen, user_id, created_by))
            
            # Obtener el DocsID generado
            cursor.execute("SELECT @@IDENTITY AS DocsID")
            docs_id = cursor.fetchone()[0]
            
            conn.commit()
            
            logger.info(f"DocsHead {docs_id} creado exitosamente para {origen}")
            return {
                'success': True,
                'docs_id': docs_id
            }
            
    except pyodbc.Error as e:
        error_msg = f"Error de base de datos al crear DocsHead: {str(e)}"
        logger.error(error_msg)
        return {
            'success': False,
            'message': 'Error al crear registro de documentos en la base de datos',
            'code': 'DATABASE_ERROR',
            'technical_error': error_msg
        }
        
    except Exception as e:
        error_msg = f"Error inesperado al crear DocsHead: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return {
            'success': False,
            'message': 'Error interno al crear registro de documentos',
            'code': 'INTERNAL_ERROR',
            'technical_error': error_msg
        }
        
    finally:
        if conn:
            try:
                conn.close()
            except:
                pass

def crear_docs_detail(docs_id: int, doc_line: int, title: str, description: str, 
                     ruta: str, file_type: str) -> Dict:
    """
    Crea un registro individual en Q_SpQ_DocsDetail
    
    Args:
        docs_id (int): ID del grupo de documentos
        doc_line (int): Número de línea del documento
        title (str): Título del archivo
        description (str): Descripción del archivo
        ruta (str): Ruta/URL del documento
        file_type (str): Tipo de archivo (extensión)
    
    Returns:
        Dict: Resultado de la operación
    """
    
    query = """
        INSERT INTO Q_SpQ_DocsDetail (
            DocsID,
            DocLine,
            Title,
            Description,
            Ruta,
            Type
        ) VALUES (?, ?, ?, ?, ?, ?)
    """

    conn = None
    try:
        conn = get_connection()
        if not conn:
            raise ConnectionError("No se pudo establecer conexión con la base de datos")
        
        with conn:
            cursor = conn.cursor()
            cursor.execute(query, (
                docs_id,
                doc_line,
                title,
                description,
                ruta,
                file_type
            ))
            
            conn.commit()
            
            doc_line_id = f"{docs_id}-{doc_line}"
            logger.info(f"DocsDetail {doc_line_id} creado exitosamente")
            
            return {
                'success': True,
                'doc_line_id': doc_line_id
            }
            
    except pyodbc.Error as e:
        error_msg = f"Error de base de datos al crear DocsDetail: {str(e)}"
        logger.error(error_msg)
        return {
            'success': False,
            'message': 'Error al guardar detalle del documento en la base de datos',
            'code': 'DATABASE_ERROR',
            'technical_error': error_msg
        }
        
    except Exception as e:
        error_msg = f"Error inesperado al crear DocsDetail: {str(e)}"
        logger.error(error_msg, exc_info=True)
        return {
            'success': False,
            'message': 'Error interno al guardar detalle del documento',
            'code': 'INTERNAL_ERROR',
            'technical_error': error_msg
        }
        
    finally:
        if conn:
            try:
                conn.close()
            except:
                pass

def obtener_siguiente_doc_line(docs_id: int) -> int:
    """
    Obtiene el siguiente número de línea disponible para un DocsID
    
    Args:
        docs_id (int): ID del grupo de documentos
    
    Returns:
        int: Siguiente número de línea disponible
    """
    
    query = """
        SELECT ISNULL(MAX(DocLine), 0) + 1 AS NextDocLine
        FROM Q_SpQ_DocsDetail
        WHERE DocsID = ?
    """

    conn = None
    try:
        conn = get_connection()
        if not conn:
            logger.warning(f"No se pudo conectar para obtener DocLine de DocsID {docs_id}")
            return 1  # Default: empezar en 1
        
        with conn:
            cursor = conn.cursor()
            cursor.execute(query, (docs_id,))
            
            row = cursor.fetchone()
            if row and row[0]:
                next_line = int(row[0])
                logger.debug(f"Siguiente DocLine para DocsID {docs_id}: {next_line}")
                return next_line
            else:
                return 1
            
    except pyodbc.Error as e:
        logger.error(f"Error de BD al obtener siguiente DocLine para DocsID {docs_id}: {str(e)}")
        return 1  # Default en caso de error
        
    except Exception as e:
        logger.error(f"Error inesperado al obtener DocLine para DocsID {docs_id}: {str(e)}")
        return 1  # Default en caso de error
        
    finally:
        if conn:
            try:
                conn.close()
            except:
                pass

def verificar_docs_head_existe(docs_id: int) -> bool:
    """
    Verifica si un DocsID existe en la tabla Q_SpQ_DocsHead
    
    Args:
        docs_id (int): ID del grupo de documentos
    
    Returns:
        bool: True si existe, False si no existe
    """
    
    query = """
        SELECT COUNT(1) AS Existe
        FROM Q_SpQ_DocsHead
        WHERE DocsID = ? AND Active = 1
    """

    conn = None
    try:
        conn = get_connection()
        if not conn:
            logger.warning(f"No se pudo conectar para verificar DocsID {docs_id}")
            return False
        
        with conn:
            cursor = conn.cursor()
            cursor.execute(query, (docs_id,))
            
            row = cursor.fetchone()
            if row and row[0]:
                existe = bool(row[0])
                logger.debug(f"DocsID {docs_id} existe: {existe}")
                return existe
            else:
                return False
            
    except pyodbc.Error as e:
        logger.error(f"Error de BD al verificar DocsID {docs_id}: {str(e)}")
        return False
        
    except Exception as e:
        logger.error(f"Error inesperado al verificar DocsID {docs_id}: {str(e)}")
        return False
        
    finally:
        if conn:
            try:
                conn.close()
            except:
                pass

def obtener_estadisticas_docs(docs_id: int) -> Dict:
    """
    Obtiene estadísticas de documentos para un DocsID
    
    Args:
        docs_id (int): ID del grupo de documentos
    
    Returns:
        Dict: Estadísticas del grupo de documentos
    """
    
    query = """
        SELECT 
            COUNT(*) AS TotalDocumentos,
            COUNT(DISTINCT Type) AS TiposArchivos,
            MIN(DocLine) AS PrimerDocLine,
            MAX(DocLine) AS UltimoDocLine
        FROM Q_SpQ_DocsDetail
        WHERE DocsID = ?
    """

    conn = None
    try:
        conn = get_connection()
        if not conn:
            return {
                'success': False,
                'message': 'No se pudo conectar a la base de datos'
            }
        
        with conn:
            cursor = conn.cursor()
            cursor.execute(query, (docs_id,))
            
            row = cursor.fetchone()
            if row:
                return {
                    'success': True,
                    'total_documentos': row[0] or 0,
                    'tipos_archivos': row[1] or 0,
                    'primer_doc_line': row[2] or 0,
                    'ultimo_doc_line': row[3] or 0
                }
            else:
                return {
                    'success': True,
                    'total_documentos': 0,
                    'tipos_archivos': 0,
                    'primer_doc_line': 0,
                    'ultimo_doc_line': 0
                }
            
    except pyodbc.Error as e:
        logger.error(f"Error de BD al obtener estadísticas para DocsID {docs_id}: {str(e)}")
        return {
            'success': False,
            'message': 'Error al consultar estadísticas de documentos'
        }
        
    except Exception as e:
        logger.error(f"Error inesperado al obtener estadísticas para DocsID {docs_id}: {str(e)}")
        return {
            'success': False,
            'message': 'Error interno al consultar estadísticas'
        }
        
    finally:
        if conn:
            try:
                conn.close()
            except:
                pass