"""
Configuración para el sistema de reportes mensuales
"""

import os
from datetime import datetime
import logging


class Config:
    """Configuración base"""
    
    # Configuración de Flask
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'tu-clave-secreta-aqui'
    DEBUG = os.environ.get('FLASK_DEBUG', 'False').lower() == 'true'
    
    # Configuración de la base de datos
    DB_SERVER = os.environ.get('DB_SERVER', 'localhost')
    DB_DATABASE = os.environ.get('DB_DATABASE', 'TRANSMISIONESMIG')
    DB_USERNAME = os.environ.get('DB_USERNAME', 'sa')
    DB_PASSWORD = os.environ.get('DB_PASSWORD', 'Sistemas123*/')
    DB_DRIVER = os.environ.get('DB_DRIVER', '{ODBC Driver 17 for SQL Server}')
    
    # Configuración de logging
    LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO')
    LOG_DIR = os.environ.get('LOG_DIR', 'logs')
    
    # Configuración de reportes
    REPORTS_AUTO_GENERATE = os.environ.get('REPORTS_AUTO_GENERATE', 'True').lower() == 'true'
    REPORTS_GENERATION_DAY_RANGE = (1, 10)  # Días del mes en que se pueden generar reportes
    
    # Configuración de archivos
    UPLOAD_FOLDER = os.environ.get('UPLOAD_FOLDER', 'uploads')
    DOWNLOAD_FOLDER = os.environ.get('DOWNLOAD_FOLDER', 'downloads')
    MAX_CONTENT_LENGTH = 16 * 1024 * 1024  # 16MB máximo
    
    # Configuración de timezone
    TIMEZONE = 'America/Bogota'
    
    @staticmethod
    def init_app(app):
        """Inicializa la configuración de la aplicación"""
        # Crear directorios necesarios
        os.makedirs(Config.LOG_DIR, exist_ok=True)
        os.makedirs(Config.UPLOAD_FOLDER, exist_ok=True)
        os.makedirs(Config.DOWNLOAD_FOLDER, exist_ok=True)
        
        # Configurar logging
        logging.basicConfig(
            level=getattr(logging, Config.LOG_LEVEL),
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler(os.path.join(Config.LOG_DIR, 'app.log')),
                logging.StreamHandler()
            ]
        )


class DevelopmentConfig(Config):
    """Configuración para desarrollo"""
    DEBUG = True


class ProductionConfig(Config):
    """Configuración para producción"""
    DEBUG = False
    LOG_LEVEL = 'WARNING'


class TestingConfig(Config):
    """Configuración para pruebas"""
    TESTING = True
    DEBUG = True
    DB_DATABASE = 'TRANSMISIONESMIG_TEST'


# Mapeo de configuraciones
config = {
    'development': DevelopmentConfig,
    'production': ProductionConfig,
    'testing': TestingConfig,
    'default': DevelopmentConfig
}


def get_config():
    """Obtiene la configuración basada en la variable de entorno"""
    return config[os.environ.get('FLASK_CONFIG', 'default')]


class DatabaseConfig:
    """Configuración específica de base de datos"""
    
    @staticmethod
    def get_connection_string():
        """Obtiene la cadena de conexión a la base de datos"""
        config_class = get_config()
        return (
            f"DRIVER={config_class.DB_DRIVER};"
            f"SERVER={config_class.DB_SERVER};"
            f"DATABASE={config_class.DB_DATABASE};"
            f"UID={config_class.DB_USERNAME};"
            f"PWD={config_class.DB_PASSWORD};"
            f"TrustServerCertificate=yes;"
        )
    
    @staticmethod
    def get_connection_params():
        """Obtiene los parámetros de conexión como diccionario"""
        config_class = get_config()
        return {
            'server': config_class.DB_SERVER,
            'database': config_class.DB_DATABASE,
            'username': config_class.DB_USERNAME,
            'password': config_class.DB_PASSWORD,
            'driver': config_class.DB_DRIVER
        }


class ReportConfig:
    """Configuración específica de reportes"""
    
    # Configuración de generación automática
    AUTO_GENERATE_ENABLED = True
    GENERATION_DAY_START = 1
    GENERATION_DAY_END = 10
    
    # Configuración de contenido
    COMPANY_INFO_REQUIRED = ['RazonSocial', 'NombreComercial']
    
    # Tablas de origen de datos
    INVOICE_TABLE = 'fe_documentos'
    EXPENSE_TABLE = 'Gastos1'
    CONTROL_TABLE = 'Control_Reportes'
    COMPANY_TABLE = 'InformacionEmpresa'
    CONFIG_TABLE = 'Configuracion'
    
    # Campos de fechas
    INVOICE_DATE_FIELD = 'fechacreacion'
    EXPENSE_DATE_FIELD = 'FechaCreacion'
    
    # Configuración de exclusiones
    EXCLUSION_CONFIG_KEY = 'idconsecutivo'
    
    @staticmethod
    def should_generate_today():
        """Verifica si hoy es un día válido para generar reportes"""
        today = datetime.now()
        return (ReportConfig.GENERATION_DAY_START <= 
                today.day <= 
                ReportConfig.GENERATION_DAY_END)
    
    @staticmethod
    def get_report_queries():
        """Obtiene las consultas SQL para los reportes"""
        return {
            'company_info': f"""
                SELECT TOP 1 RazonSocial, NombreComercial 
                FROM {ReportConfig.COMPANY_TABLE} WITH(NOLOCK)
            """,
            
            'invoice_stats_with_exclusion': f"""
                SELECT 
                    COUNT(*) as DocumentosTransmitidos,
                    SUM(CASE WHEN fd.transmitido = 1 THEN 1 ELSE 0 END) as DocumentosExitosos,
                    SUM(CASE WHEN fd.recibido = 1 THEN 1 ELSE 0 END) as DocumentosRecibidos,
                    SUM(CASE WHEN fd.aceptacion = 1 THEN 1 ELSE 0 END) as DocumentosAceptados,
                    SUM(CASE WHEN fd.rechazo = 1 THEN 1 ELSE 0 END) as DocumentosRechazados,
                    ISNULL(SUM(fd.subtotal), 0) as TotalSubtotal,
                    ISNULL(SUM(fd.iva), 0) as TotalIVA,
                    ISNULL(SUM(fd.valor), 0) as TotalValor
                FROM {ReportConfig.INVOICE_TABLE} fd WITH(NOLOCK)
                LEFT JOIN Facturas1 f1 WITH(NOLOCK) ON fd.documento = f1.Numero
                WHERE fd.{ReportConfig.INVOICE_DATE_FIELD} BETWEEN ? AND ?
                AND (f1.IdConsecutivo IS NULL OR f1.IdConsecutivo <> ?)
            """,
            
            'invoice_stats_no_exclusion': f"""
                SELECT 
                    COUNT(*) as DocumentosTransmitidos,
                    SUM(CASE WHEN transmitido = 1 THEN 1 ELSE 0 END) as DocumentosExitosos,
                    SUM(CASE WHEN recibido = 1 THEN 1 ELSE 0 END) as DocumentosRecibidos,
                    SUM(CASE WHEN aceptacion = 1 THEN 1 ELSE 0 END) as DocumentosAceptados,
                    SUM(CASE WHEN rechazo = 1 THEN 1 ELSE 0 END) as DocumentosRechazados,
                    ISNULL(SUM(subtotal), 0) as TotalSubtotal,
                    ISNULL(SUM(iva), 0) as TotalIVA,
                    ISNULL(SUM(valor), 0) as TotalValor
                FROM {ReportConfig.INVOICE_TABLE} WITH(NOLOCK)
                WHERE {ReportConfig.INVOICE_DATE_FIELD} BETWEEN ? AND ?
            """,
            
            'expense_stats': f"""
                SELECT 
                    COUNT(*) as DocumentosTransmitidos,
                    SUM(CASE WHEN transmitido = 1 THEN 1 ELSE 0 END) as DocumentosExitosos,
                    0 as DocumentosRecibidos,
                    0 as DocumentosAceptados,
                    0 as DocumentosRechazados,
                    ISNULL(SUM(subtotal), 0) as TotalSubtotal,
                    ISNULL(SUM(totaliva), 0) as TotalIVA,
                    ISNULL(SUM(total), 0) as TotalValor
                FROM {ReportConfig.EXPENSE_TABLE} WITH(NOLOCK)
                WHERE {ReportConfig.EXPENSE_DATE_FIELD} BETWEEN ? AND ?
            """,
            
            'config_value': f"""
                SELECT Valor FROM {ReportConfig.CONFIG_TABLE} WHERE Clave = ?
            """,
            
            'report_exists': f"""
                SELECT COUNT(*) as count FROM {ReportConfig.CONTROL_TABLE} 
                WHERE Periodo = ? AND Enviado = 1
            """,
            
            'all_reports': f"""
                SELECT 
                    ID as id,
                    Periodo as periodo,
                    FechaEnvio as fecha_envio,
                    TotalDocumentos as total_documentos,
                    DocumentosExitosos as documentos_exitosos,
                    ValorTotal as valor_total,
                    TasaExito as tasa_exito,
                    Observaciones as observaciones,
                    CASE 
                        WHEN Enviado = 1 THEN 'completed'
                        ELSE 'pending'
                    END as status
                FROM {ReportConfig.CONTROL_TABLE}
                ORDER BY Periodo DESC
            """,
            
            'report_detail': f"""
                SELECT 
                    ID as id,
                    Periodo as periodo,
                    FechaEnvio as fecha_envio,
                    TotalDocumentos as total_documentos,
                    DocumentosExitosos as documentos_exitosos,
                    ValorTotal as valor_total,
                    TasaExito as tasa_exito,
                    Observaciones as observaciones,
                    ContenidoCompleto as contenido_completo,
                    DetalleFacturas as detalle_facturas,
                    DetalleGastos as detalle_gastos,
                    CASE 
                        WHEN Enviado = 1 THEN 'completed'
                        ELSE 'pending'
                    END as status
                FROM {ReportConfig.CONTROL_TABLE}
                WHERE ID = ?
            """,
            
            'last_report': f"""
                SELECT TOP 1 Periodo as periodo, FechaEnvio as fecha_envio
                FROM {ReportConfig.CONTROL_TABLE} 
                WHERE Enviado = 1
                ORDER BY FechaEnvio DESC
            """,
            
            'periods_by_year': f"""
                SELECT Periodo FROM {ReportConfig.CONTROL_TABLE} 
                WHERE Periodo LIKE ? AND Enviado = 1
            """
        }


class LoggingConfig:
    """Configuración de logging"""
    
    @staticmethod
    def setup_logging(app):
        """Configura el sistema de logging"""
        if not app.debug:
            # Configuración para producción
            file_handler = logging.FileHandler(
                os.path.join(Config.LOG_DIR, 'app.log')
            )
            file_handler.setFormatter(logging.Formatter(
                '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
            ))
            file_handler.setLevel(logging.INFO)
            app.logger.addHandler(file_handler)
            
            app.logger.setLevel(logging.INFO)
            app.logger.info('Aplicación de reportes iniciada')
        
        # Handler específico para reportes
        report_handler = logging.FileHandler(
            os.path.join(Config.LOG_DIR, 'reportes.log')
        )
        report_handler.setFormatter(logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        ))
        
        report_logger = logging.getLogger('reportes')
        report_logger.addHandler(report_handler)
        report_logger.setLevel(logging.INFO)


class SecurityConfig:
    """Configuración de seguridad"""
    
    # Headers de seguridad
    SECURITY_HEADERS = {
        'X-Content-Type-Options': 'nosniff',
        'X-Frame-Options': 'DENY',
        'X-XSS-Protection': '1; mode=block',
    }
    
    # CORS
    CORS_ORIGINS = [
        'http://localhost:3000',
        'http://localhost:8000',
        'http://127.0.0.1:8000',
    ]
    
    # Rate limiting (requests per minute)
    RATE_LIMIT = {
        'default': 100,
        'api': 60,
        'generate_report': 5,
        'verify_missing': 2
    }


class TemplateConfig:
    """Configuración de templates"""
    
    TEMPLATE_FOLDER = 'templates'
    STATIC_FOLDER = 'static'
    
    # Configuración de Jinja2
    JINJA2_CONFIG = {
        'auto_reload': True,
        'autoescape': True
    }


# Función para obtener toda la configuración
def get_full_config():
    """Obtiene la configuración completa del sistema"""
    config_class = get_config()
    return {
        'flask': config_class,
        'database': DatabaseConfig,
        'reports': ReportConfig,
        'security': SecurityConfig,
        'templates': TemplateConfig
    }