# app.py - Archivo principal de Flask - VERSIÓN COMPLETA CON ENDPOINT FALTANTE
from flask import Flask, request, jsonify, send_file, render_template
from flask_cors import CORS
import os
import shutil
from datetime import datetime
import re
import json
import logging
import base64
from io import BytesIO
from PIL import Image
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.units import inch
from reportlab.lib.colors import black, blue
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image as ReportLabImage
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from werkzeug.utils import secure_filename
import urllib.parse
import unicodedata

app = Flask(__name__)
CORS(app)

# Configuración
UPLOAD_FOLDER = 'documentos'
FIRMADOS_FOLDER = 'documentos/firmados'
FIRMAS_FOLDER = 'documentos/firmas_digitales'
LOG_FILE = 'documentos/firmados/registro_firmas.log'
TERMINOS_ORIGINAL = 'documentos/Terminos_y_Condiciones_Sistemas_MiG_SAS.pdf'

# Crear directorios necesarios
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(FIRMADOS_FOLDER, exist_ok=True)
os.makedirs(FIRMAS_FOLDER, exist_ok=True)

# Configurar logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def limpiar_nombre_archivo(texto):
    """Limpia un texto para usarlo como nombre de archivo"""
    # Normalizar caracteres unicode (Ñ -> N, á -> a, etc.)
    texto = unicodedata.normalize('NFKD', texto)
    texto = texto.encode('ASCII', 'ignore').decode('ASCII')
    # Eliminar caracteres especiales
    texto_limpio = re.sub(r'[^\w\s-]', '', texto)
    texto_limpio = re.sub(r'[-\s]+', '_', texto_limpio)
    return texto_limpio.strip('_')[:50]

def log_evento(mensaje):
    """Registra eventos en el archivo de log"""
    timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    with open(LOG_FILE, 'a', encoding='utf-8') as f:
        f.write(f"[{timestamp}] {mensaje}\n")

def buscar_firma_por_nit_y_comercial(nit, nombre_comercial):
    """
    Busca si existe una firma/aceptación para la combinación específica de NIT + Nombre Comercial
    """
    try:
        nit_limpio = limpiar_nombre_archivo(nit)
        comercial_limpio = limpiar_nombre_archivo(nombre_comercial)
        
        archivos_coincidentes = []
        
        for archivo in os.listdir(FIRMADOS_FOLDER):
            if archivo.endswith('.pdf'):
                # El nombre del archivo debe contener tanto el NIT como el nombre comercial
                if archivo.startswith(f"{nit_limpio}_{comercial_limpio}_"):
                    ruta_completa = os.path.join(FIRMADOS_FOLDER, archivo)
                    fecha_creacion = datetime.fromtimestamp(os.path.getctime(ruta_completa))
                    archivos_coincidentes.append({
                        'archivo': archivo,
                        'fecha': fecha_creacion.strftime('%Y-%m-%d %H:%M:%S'),
                        'timestamp': fecha_creacion
                    })
        
        if archivos_coincidentes:
            archivos_coincidentes.sort(key=lambda x: x['timestamp'], reverse=True)
            return archivos_coincidentes[0]
        
        return None
        
    except Exception as e:
        logger.error(f"Error buscando firma para NIT {nit} y comercial {nombre_comercial}: {str(e)}")
        return None

def crear_certificado_aceptacion(nit, razon_social, nombre_comercial):
    """
    Crea un certificado de aceptación de términos sin firma dibujada
    """
    try:
        logger.info("=== CREANDO CERTIFICADO DE ACEPTACIÓN ===")
        
        nit_limpio = limpiar_nombre_archivo(nit)
        razon_limpia = limpiar_nombre_archivo(razon_social)
        nombre_limpio = limpiar_nombre_archivo(nombre_comercial)
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        
        nombre_archivo = f"{nit_limpio}_{nombre_limpio}_{razon_limpia}_{timestamp}.pdf"
        ruta_destino = os.path.join(FIRMADOS_FOLDER, nombre_archivo)
        
        # Intentar copiar el PDF original primero
        if os.path.exists(TERMINOS_ORIGINAL):
            try:
                import pypdf
                from reportlab.pdfgen import canvas
                from reportlab.lib.pagesizes import A4
                import io
                
                logger.info("Combinando PDF original con página de aceptación...")
                
                buffer = io.BytesIO()
                c = canvas.Canvas(buffer, pagesize=A4)
                width, height = A4
                
                c.setFont("Helvetica-Bold", 16)
                c.drawCentredString(width/2, height - 100, "CERTIFICADO DE ACEPTACIÓN")
                c.drawCentredString(width/2, height - 130, "TÉRMINOS Y CONDICIONES")
                
                c.setFont("Helvetica", 12)
                y_pos = height - 200
                
                c.drawString(50, y_pos, f"Empresa: {razon_social}")
                c.drawString(50, y_pos - 25, f"Nombre Comercial: {nombre_comercial}")
                c.drawString(50, y_pos - 50, f"NIT: {nit}")
                c.drawString(50, y_pos - 75, f"Fecha de Aceptación: {datetime.now().strftime('%d/%m/%Y %H:%M:%S')}")
                c.drawString(50, y_pos - 100, f"Dirección IP: {request.remote_addr if request else 'N/A'}")
                
                c.setFont("Helvetica", 10)
                c.drawString(50, y_pos - 150, "El representante legal de la empresa mencionada declara que:")
                c.drawString(50, y_pos - 170, "✓ Ha leído completamente los términos y condiciones")
                c.drawString(50, y_pos - 190, "✓ Comprende y acepta todas las cláusulas establecidas")
                c.drawString(50, y_pos - 210, "✓ Tiene autoridad para representar y obligar a la empresa")
                c.drawString(50, y_pos - 230, "✓ Acepta que este acto tiene validez legal")
                
                c.setFont("Helvetica-Bold", 10)
                c.drawString(50, y_pos - 280, "Este documento certifica la aceptación electrónica de los términos y condiciones")
                c.drawString(50, y_pos - 300, "de MIG SISTEMAS SAS conforme a la Ley 527 de 1999.")
                
                c.save()
                buffer.seek(0)
                
                writer = pypdf.PdfWriter()
                
                with open(TERMINOS_ORIGINAL, 'rb') as original_file:
                    reader = pypdf.PdfReader(original_file)
                    for page in reader.pages:
                        writer.add_page(page)
                
                aceptacion_reader = pypdf.PdfReader(buffer)
                writer.add_page(aceptacion_reader.pages[0])
                
                with open(ruta_destino, 'wb') as output_file:
                    writer.write(output_file)
                
                logger.info(f"✓ Certificado creado con PDF original + aceptación")
                return nombre_archivo, ruta_destino
                
            except Exception as e:
                logger.warning(f"No se pudo combinar, creando certificado simple: {e}")
        
        logger.info("Creando certificado completo con ReportLab...")
        
        doc = SimpleDocTemplate(ruta_destino, pagesize=A4, topMargin=50, bottomMargin=50)
        story = []
        styles = getSampleStyleSheet()
        
        titulo_style = ParagraphStyle(
            'TituloCustom',
            parent=styles['Heading1'],
            fontSize=18,
            spaceAfter=20,
            alignment=1,
            textColor=black
        )
        
        subtitulo_style = ParagraphStyle(
            'SubtituloCustom',
            parent=styles['Heading2'],
            fontSize=14,
            spaceAfter=15,
            textColor=black
        )
        
        normal_style = ParagraphStyle(
            'NormalCustom',
            parent=styles['Normal'],
            fontSize=11,
            spaceAfter=10,
            alignment=4,
            textColor=black
        )
        
        titulo = Paragraph("CERTIFICADO DE ACEPTACIÓN DIGITAL", titulo_style)
        story.append(titulo)
        
        subtitulo = Paragraph("TÉRMINOS Y CONDICIONES - MIG SISTEMAS SAS", subtitulo_style)
        story.append(subtitulo)
        story.append(Spacer(1, 30))
        
        info_empresa = f"""
        <b>DATOS DE LA EMPRESA QUE ACEPTA:</b><br/><br/>
        <b>Razón Social:</b> {razon_social}<br/>
        <b>Nombre Comercial:</b> {nombre_comercial}<br/>
        <b>NIT:</b> {nit}<br/>
        <b>Fecha y Hora de Aceptación:</b> {datetime.now().strftime('%d/%m/%Y %H:%M:%S')}<br/>
        <b>Dirección IP:</b> {request.remote_addr if request else 'N/A'}
        """
        story.append(Paragraph(info_empresa, normal_style))
        story.append(Spacer(1, 30))
        
        declaracion = """
        <b>DECLARACIÓN DE ACEPTACIÓN:</b><br/><br/>
        El representante legal de la empresa mencionada declara bajo la gravedad de juramento que:<br/><br/>
        ✓ Ha leído completamente los términos y condiciones de uso del software SISTEMAS MIG<br/>
        ✓ Comprende y acepta todas las cláusulas, obligaciones y condiciones establecidas<br/>
        ✓ Tiene plena autoridad para representar y obligar legalmente a la empresa<br/>
        ✓ Acepta que este acto de aceptación electrónica tiene plena validez legal<br/>
        ✓ Se compromete a cumplir con todas las obligaciones contractuales establecidas
        """
        story.append(Paragraph(declaracion, normal_style))
        story.append(Spacer(1, 30))
        
        resumen = """
        <b>RESUMEN DE TÉRMINOS PRINCIPALES:</b><br/><br/>
        <b>1. OBJETO:</b> Licencia de uso no exclusiva del software SISTEMAS MIG<br/>
        <b>2. ALCANCE:</b> Facturación POS, administrativo, inventarios, informes fiscales<br/>
        <b>3. OBLIGACIONES USUARIO:</b> Pagos al día, copias de seguridad, protección con antivirus<br/>
        <b>4. OBLIGACIONES MIG:</b> Instalación, actualizaciones, soporte técnico<br/>
        <b>5. HORARIOS SOPORTE:</b> Lun-Vie 8:00-16:00, facturación 7x24<br/>
        <b>6. PAGOS:</b> Cuenta Bancolombia 00449206584 SISTEMAS MIG S.A.S<br/>
        <b>7. GARANTÍA:</b> Corrección de errores con pagos al día<br/>
        <b>8. DOMICILIO:</b> Medellín, Antioquia, Colombia
        """
        story.append(Paragraph(resumen, normal_style))
        story.append(Spacer(1, 30))
        
        nota_legal = """
        <b>VALIDEZ LEGAL:</b><br/>
        Este documento certifica la aceptación electrónica de los términos y condiciones de MIG SISTEMAS SAS.
        Conforme a la Ley 527 de 1999 sobre comercio electrónico y firmas digitales, y el Decreto 2364 de 2012,
        esta aceptación tiene plena validez legal y constituye un acuerdo vinculante entre las partes.<br/><br/>
        El documento completo de términos y condiciones está disponible en: https://www.migsistemas.net/
        """
        story.append(Paragraph(nota_legal, normal_style))
        story.append(Spacer(1, 40))
        
        pie = """
        <b>SISTEMAS MIG S.A.S</b><br/>
        NIT: 900.275.400-8<br/>
        Centro de Negocios Alcalá, Carrera 43B N° 14-51 Local 1<br/>
        Medellín - Antioquia, Colombia<br/>
        Tel: 300 762 1171 | info@migsistemas.com
        """
        story.append(Paragraph(pie, normal_style))
        
        doc.build(story)
        
        logger.info(f"✓ Certificado de aceptación creado: {ruta_destino}")
        return nombre_archivo, ruta_destino
        
    except Exception as e:
        logger.error(f"Error creando certificado: {str(e)}")
        import traceback
        logger.error(f"Traceback: {traceback.format_exc()}")
        return None, None

# ==================== ENDPOINTS ====================

@app.route('/')
def index():
    return render_template('index.html')

# API: Verificar firma por NIT (método original)
@app.route('/api/verificar-firma/<nit>', methods=['GET'])
def verificar_firma(nit):
    try:
        nit_limpio = limpiar_nombre_archivo(nit)
        
        archivos_firmados = []
        for archivo in os.listdir(FIRMADOS_FOLDER):
            if archivo.startswith(f"{nit_limpio}_") and archivo.endswith('.pdf'):
                ruta_completa = os.path.join(FIRMADOS_FOLDER, archivo)
                fecha_creacion = datetime.fromtimestamp(os.path.getctime(ruta_completa))
                archivos_firmados.append({
                    'archivo': archivo,
                    'fecha': fecha_creacion.strftime('%Y-%m-%d %H:%M:%S')
                })
        
        if archivos_firmados:
            archivos_firmados.sort(key=lambda x: x['fecha'], reverse=True)
            ultimo_archivo = archivos_firmados[0]
            
            return jsonify({
                'firmado': True,
                'fecha_firma': ultimo_archivo['fecha'],
                'archivo': ultimo_archivo['archivo'],
                'total_firmas': len(archivos_firmados)
            })
        else:
            return jsonify({'firmado': False})
            
    except Exception as e:
        logger.error(f"Error verificando firma para NIT {nit}: {str(e)}")
        return jsonify({'error': f'Error al verificar firma: {str(e)}'}), 500

# API: Verificar firma por NIT + Nombre Comercial
@app.route('/api/verificar-firma-comercial/<nit>/<nombre_comercial>', methods=['GET'])
def verificar_firma_comercial(nit, nombre_comercial):
    try:
        nit = urllib.parse.unquote(nit)
        nombre_comercial = urllib.parse.unquote(nombre_comercial)
        
        logger.info(f"Verificando firma para NIT: {nit}, Nombre Comercial: {nombre_comercial}")
        
        resultado = buscar_firma_por_nit_y_comercial(nit, nombre_comercial)
        
        if resultado:
            logger.info(f"Firma encontrada para {nit} - {nombre_comercial}: {resultado['archivo']}")
            return jsonify({
                'firmado': True,
                'fecha_firma': resultado['fecha'],
                'archivo': resultado['archivo'],
                'nit': nit,
                'nombre_comercial': nombre_comercial,
                'total_firmas': 1
            })
        else:
            logger.info(f"No se encontró firma para {nit} - {nombre_comercial}")
            return jsonify({
                'firmado': False,
                'nit': nit,
                'nombre_comercial': nombre_comercial
            })
            
    except Exception as e:
        logger.error(f"Error verificando firma comercial para NIT {nit}, Comercial {nombre_comercial}: {str(e)}")
        return jsonify({'error': f'Error al verificar firma comercial: {str(e)}'}), 500

# API: NUEVO - Verificar aceptación (alias de verificar-firma-comercial)
@app.route('/api/verificar-aceptacion/<nit>/<nombre_comercial>', methods=['GET'])
def verificar_aceptacion(nit, nombre_comercial):
    """
    Endpoint para verificar aceptación de términos
    Usado por la aplicación C# - redirige a la lógica de verificar-firma-comercial
    """
    try:
        nit = urllib.parse.unquote(nit)
        nombre_comercial = urllib.parse.unquote(nombre_comercial)
        
        logger.info(f"[ACEPTACIÓN] Verificando para NIT: {nit}, Nombre Comercial: {nombre_comercial}")
        
        resultado = buscar_firma_por_nit_y_comercial(nit, nombre_comercial)
        
        if resultado:
            logger.info(f"[ACEPTACIÓN] Encontrada para {nit} - {nombre_comercial}")
            return jsonify({
                'firmado': True,
                'fecha_firma': resultado['fecha'],
                'archivo': resultado['archivo'],
                'nit': nit,
                'nombre_comercial': nombre_comercial
            })
        else:
            logger.info(f"[ACEPTACIÓN] No encontrada para {nit} - {nombre_comercial}")
            return jsonify({
                'firmado': False,
                'nit': nit,
                'nombre_comercial': nombre_comercial
            })
            
    except Exception as e:
        logger.error(f"[ACEPTACIÓN] Error para NIT {nit}, Comercial {nombre_comercial}: {str(e)}")
        return jsonify({'error': f'Error al verificar aceptación: {str(e)}'}), 500

# API: Obtener términos PDF
@app.route('/api/obtener-terminos', methods=['GET'])
def obtener_terminos():
    try:
        if not os.path.exists(TERMINOS_ORIGINAL):
            return jsonify({'error': 'Archivo de términos no encontrado'}), 404
            
        return send_file(
            TERMINOS_ORIGINAL,
            as_attachment=True,
            download_name='Terminos_y_Condiciones_Sistemas_MiG_SAS.pdf',
            mimetype='application/pdf'
        )
    except Exception as e:
        logger.error(f"Error obteniendo términos: {str(e)}")
        return jsonify({'error': f'Error al obtener términos: {str(e)}'}), 500

# API: Aceptar términos
@app.route('/api/aceptar-terminos', methods=['POST'])
def aceptar_terminos():
    try:
        logger.info("=== INICIANDO PROCESO DE ACEPTACIÓN ===")
        
        data = request.get_json()
        
        if not data:
            return jsonify({'error': 'No se recibieron datos'}), 400
        
        nit = data.get('nit', '').strip()
        razon_social = data.get('razon_social', '').strip()
        nombre_comercial = data.get('nombre_comercial', '').strip()
        ip_cliente = request.remote_addr
        
        logger.info(f"Datos recibidos - NIT: {nit}, Razón: {razon_social}, Comercial: {nombre_comercial}")
        
        if not nit or not razon_social or not nombre_comercial:
            return jsonify({'error': 'Faltan datos obligatorios: NIT, Razón Social y Nombre Comercial'}), 400
        
        nombre_archivo, ruta_pdf = crear_certificado_aceptacion(nit, razon_social, nombre_comercial)
        
        if not nombre_archivo:
            logger.error("Error creando el certificado de aceptación")
            return jsonify({'error': 'Error creando el certificado de aceptación'}), 500
        
        mensaje_log = (
            f"ACEPTACIÓN REGISTRADA - NIT: {nit} | Razón Social: {razon_social} | "
            f"Nombre Comercial: {nombre_comercial} | IP: {ip_cliente} | "
            f"Archivo: {nombre_archivo}"
        )
        log_evento(mensaje_log)
        
        logger.info(f"=== PROCESO COMPLETADO EXITOSAMENTE ===")
        
        return jsonify({
            'exito': True,
            'mensaje': 'Términos y condiciones aceptados exitosamente',
            'archivo': nombre_archivo,
            'fecha': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'nit': nit,
            'razon_social': razon_social,
            'nombre_comercial': nombre_comercial
        })
        
    except Exception as e:
        logger.error(f"Error en endpoint aceptar-terminos: {str(e)}")
        import traceback
        logger.error(f"Traceback completo: {traceback.format_exc()}")
        return jsonify({'error': f'Error al aceptar términos: {str(e)}'}), 500

# API: Listar todas las firmas
@app.route('/api/listar-firmas', methods=['GET'])
def listar_firmas():
    try:
        firmas = []
        
        if os.path.exists(FIRMADOS_FOLDER):
            for archivo in os.listdir(FIRMADOS_FOLDER):
                if archivo.endswith('.pdf'):
                    ruta_completa = os.path.join(FIRMADOS_FOLDER, archivo)
                    fecha_creacion = datetime.fromtimestamp(os.path.getctime(ruta_completa))
                    tamaño = os.path.getsize(ruta_completa)
                    
                    partes = archivo.replace('.pdf', '').split('_')
                    if len(partes) >= 4:
                        nit = partes[0]
                        nombre_comercial = partes[1]
                        fecha_archivo = f"{partes[-2]}_{partes[-1]}"
                        razon_social = '_'.join(partes[2:-2]) if len(partes) > 4 else 'N/A'
                    else:
                        nit = partes[0] if len(partes) > 0 else 'N/A'
                        nombre_comercial = 'N/A'
                        fecha_archivo = 'N/A'
                        razon_social = 'N/A'
                    
                    firmas.append({
                        'archivo': archivo,
                        'nit': nit,
                        'nombre_comercial': nombre_comercial,
                        'razon_social': razon_social,
                        'fecha_creacion': fecha_creacion.strftime('%Y-%m-%d %H:%M:%S'),
                        'tamaño_bytes': tamaño,
                        'tamaño_mb': round(tamaño / 1024 / 1024, 2),
                        'identificador_unico': f"{nit}_{nombre_comercial}"
                    })
        
        firmas.sort(key=lambda x: x['fecha_creacion'], reverse=True)
        
        return jsonify({
            'total': len(firmas),
            'firmas': firmas
        })
        
    except Exception as e:
        logger.error(f"Error listando firmas: {str(e)}")
        return jsonify({'error': f'Error al listar firmas: {str(e)}'}), 500

# API: Estadísticas
@app.route('/api/estadisticas', methods=['GET'])
def estadisticas():
    try:
        total_firmas = 0
        tamaño_total = 0
        empresas_unicas = set()
        establecimientos_unicos = set()
        
        if os.path.exists(FIRMADOS_FOLDER):
            for archivo in os.listdir(FIRMADOS_FOLDER):
                if archivo.endswith('.pdf'):
                    ruta_completa = os.path.join(FIRMADOS_FOLDER, archivo)
                    total_firmas += 1
                    tamaño_total += os.path.getsize(ruta_completa)
                    
                    partes = archivo.replace('.pdf', '').split('_')
                    if len(partes) >= 2:
                        nit = partes[0]
                        nombre_comercial = partes[1]
                        empresas_unicas.add(nit)
                        establecimientos_unicos.add(f"{nit}_{nombre_comercial}")
        
        return jsonify({
            'total_firmas': total_firmas,
            'total_empresas_unicas': len(empresas_unicas),
            'total_establecimientos_unicos': len(establecimientos_unicos),
            'tamaño_total_mb': round(tamaño_total / 1024 / 1024, 2),
            'archivo_original_existe': os.path.exists(TERMINOS_ORIGINAL),
            'fecha_consulta': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        })
        
    except Exception as e:
        logger.error(f"Error obteniendo estadísticas: {str(e)}")
        return jsonify({'error': f'Error al obtener estadísticas: {str(e)}'}), 500

# Manejo de errores
@app.errorhandler(404)
def not_found(error):
    return jsonify({'error': 'Endpoint no encontrado'}), 404

@app.errorhandler(500)
def internal_error(error):
    return jsonify({'error': 'Error interno del servidor'}), 500

if __name__ == '__main__':
    if not os.path.exists(TERMINOS_ORIGINAL):
        logger.warning(f"Archivo de términos no encontrado en {TERMINOS_ORIGINAL}")
    
    logger.info("=== SERVIDOR INICIADO ===")
    logger.info("Endpoints disponibles:")
    logger.info("- /api/verificar-firma/<nit>")
    logger.info("- /api/verificar-firma-comercial/<nit>/<nombre_comercial>")
    logger.info("- /api/verificar-aceptacion/<nit>/<nombre_comercial> [NUEVO]")
    logger.info("- /api/aceptar-terminos")
    
    app.run(debug=True, host='0.0.0.0', port=97)