"""
Servicio para generar PDFs profesionales usando WeasyPrint y plantillas HTML/CSS
"""
import os
import tempfile
import platform
import socket
from datetime import datetime
from flask import render_template, current_app, url_for, request
from io import BytesIO
from urllib.parse import urljoin

# Detectar si estamos en un entorno de servidor
def is_server_environment():
    """Detecta si estamos en un entorno de servidor"""
    # Verificar si estamos en un entorno de producción según variable de entorno
    if os.environ.get('FLASK_ENV') == 'production':
        return True
    
    # Verificar si estamos en un servidor por nombre de host
    hostname = socket.gethostname()
    if 'bluehost' in hostname.lower() or '.com' in hostname:
        return True
        
    return False

# Intentar importar bibliotecas de PDF en orden de preferencia
PLAYWRIGHT_AVAILABLE = False
if not is_server_environment():  # Solo intentar usar Playwright en entorno local
    try:
        from playwright.sync_api import sync_playwright
        PLAYWRIGHT_AVAILABLE = True
    except ImportError:
        PLAYWRIGHT_AVAILABLE = False

# WeasyPrint importación diferida para evitar bloqueo del sistema
WEASYPRINT_AVAILABLE = False
def _import_weasyprint():
    global WEASYPRINT_AVAILABLE
    try:
        from weasyprint import HTML, CSS
        WEASYPRINT_AVAILABLE = True
        return HTML, CSS
    except Exception as e:
        WEASYPRINT_AVAILABLE = False
        return None, None
    
try:
    import pdfkit
    PDFKIT_AVAILABLE = True
except ImportError:
    PDFKIT_AVAILABLE = False

# Importar ReportLab como último fallback
try:
    from reportlab.lib.pagesizes import A4
    from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
    from reportlab.lib.styles import getSampleStyleSheet
    REPORTLAB_AVAILABLE = True
except ImportError:
    REPORTLAB_AVAILABLE = False


def generate_proposal_pdf_playwright(proposal_data, invoice_data, commercial):
    """
    Genera un PDF profesional usando Playwright (navegador headless)
    """
    try:
        # Calcular URL absoluta de la foto del asesor (con fallback)
        advisor_image_url = url_for('static', filename='img/LOGO-OLE-CONTULTING-COLOR.png', _external=True)
        if commercial:
            # Preferir la propiedad profile_image_url si está disponible
            img_candidate = getattr(commercial, 'profile_image_url', None)
            if img_candidate:
                img = str(img_candidate)
                if img.startswith('http://') or img.startswith('https://') or img.startswith('data:'):
                    advisor_image_url = img
                elif img.startswith('/'):
                    advisor_image_url = urljoin(request.url_root, img.lstrip('/'))
                else:
                    advisor_image_url = urljoin(request.url_root, img)
            elif getattr(commercial, 'profile_image', None):
                img = str(commercial.profile_image)
                if img.startswith('http://') or img.startswith('https://') or img.startswith('data:'):
                    advisor_image_url = img
                elif img.startswith('/static/'):
                    advisor_image_url = urljoin(request.url_root, img.lstrip('/'))
                elif img.startswith('static/'):
                    advisor_image_url = urljoin(request.url_root, img)
                else:
                    # Caso común: en DB guardamos solo el nombre de archivo
                    advisor_image_url = url_for('static', filename=f'uploads/profiles/{os.path.basename(img)}', _external=True)

        # Preparar datos para la plantilla
        template_data = {
            'proposal_data': proposal_data,
            'invoice_data': invoice_data,
            'commercial': commercial,
            'current_date': datetime.now().strftime('%d/%m/%Y'),
            'advisor_image_url': advisor_image_url
        }
        
        # Renderizar la plantilla HTML con estilos completos
        html_content = render_template('Private_Invoice/propuesta_pdf_simple.html', **template_data)
        
        # DIAGNÓSTICO: Guardar HTML intermedio para verificar estilos
        debug_path = os.path.join(tempfile.gettempdir(), 'debug_propuesta.html')
        with open(debug_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        current_app.logger.info(f"HTML de diagnóstico guardado en: {debug_path}")
        
        # Usar Playwright para generar PDF
        with sync_playwright() as p:
            browser = p.chromium.launch()
            # Crear contexto con base_url para resolver rutas relativas
            context = browser.new_context(base_url=request.url_root)
            page = context.new_page()
            page.set_content(html_content, wait_until='networkidle')
            # Esperar a que terminen las solicitudes de red (imágenes, CSS)
            try:
                page.wait_for_load_state('networkidle')
            except Exception as e:
                current_app.logger.warning(f"Timeout esperando recursos en Playwright: {e}")
            
            # Configuración del PDF
            pdf_data = page.pdf(
                format='A4',
                margin={
                    'top': '20mm',
                    'right': '20mm', 
                    'bottom': '20mm',
                    'left': '20mm'
                },
                print_background=True
            )
            context.close()
            browser.close()
        
        # Crear buffer
        pdf_buffer = BytesIO()
        pdf_buffer.write(pdf_data)
        pdf_buffer.seek(0)
        
        return pdf_buffer
        
    except Exception as e:
        current_app.logger.error(f"Error generando PDF con Playwright: {str(e)}")
        # Fallback a WeasyPrint si Playwright falla
        return generate_proposal_pdf_weasyprint(proposal_data, invoice_data, commercial)


def generate_proposal_pdf_weasyprint(proposal_data, invoice_data, commercial):
    """
    Genera un PDF profesional usando WeasyPrint y plantillas HTML/CSS
    """
    try:
        # Importar WeasyPrint solo cuando sea necesario
        HTML, CSS = _import_weasyprint()
        if not HTML or not CSS:
            raise ImportError("WeasyPrint no disponible")
            
        # Calcular URL absoluta de la foto del asesor (con fallback)
        advisor_image_url = url_for('static', filename='img/LOGO-OLE-CONTULTING-COLOR.png', _external=True)
        if commercial:
            img_candidate = getattr(commercial, 'profile_image_url', None)
            if img_candidate:
                img = str(img_candidate)
                if img.startswith('http://') or img.startswith('https://') or img.startswith('data:'):
                    advisor_image_url = img
                elif img.startswith('/'):
                    advisor_image_url = urljoin(request.url_root, img.lstrip('/'))
                else:
                    advisor_image_url = urljoin(request.url_root, img)
            elif getattr(commercial, 'profile_image', None):
                img = str(commercial.profile_image)
                if img.startswith('http://') or img.startswith('https://') or img.startswith('data:'):
                    advisor_image_url = img
                elif img.startswith('/static/'):
                    advisor_image_url = urljoin(request.url_root, img.lstrip('/'))
                elif img.startswith('static/'):
                    advisor_image_url = urljoin(request.url_root, img)
                else:
                    advisor_image_url = url_for('static', filename=f'uploads/profiles/{os.path.basename(img)}', _external=True)

        # Preparar datos para la plantilla
        template_data = {
            'proposal_data': proposal_data,
            'invoice_data': invoice_data,
            'commercial': commercial,
            'current_date': datetime.now().strftime('%d/%m/%Y'),
            'advisor_image_url': advisor_image_url
        }
        
        # Renderizar la plantilla HTML con estilos completos
        html_content = render_template('Private_Invoice/propuesta_pdf_simple.html', **template_data)
        
        # DIAGNÓSTICO: Guardar HTML intermedio para verificar estilos
        debug_path = os.path.join(tempfile.gettempdir(), 'debug_propuesta.html')
        with open(debug_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        current_app.logger.info(f"HTML de diagnóstico guardado en: {debug_path}")
        
        # Crear el PDF usando WeasyPrint
        html_doc = HTML(string=html_content, base_url=request.url_root)
        pdf_buffer = BytesIO()
        # Corregir llamada a write_pdf (no pasar argumentos adicionales)
        pdf_buffer.write(html_doc.write_pdf())
        
        pdf_buffer.seek(0)
        return pdf_buffer
        
    except Exception as e:
        current_app.logger.error(f"Error generando PDF con WeasyPrint: {str(e)}")
        # Fallback a método simple si WeasyPrint falla
        return generate_proposal_pdf_fallback(proposal_data, invoice_data, commercial)


def generate_proposal_pdf_pdfkit(proposal_data, invoice_data, commercial):
    """
    Genera un PDF usando pdfkit (fallback si WeasyPrint no funciona)
    """
    if not PDFKIT_AVAILABLE:
        return generate_proposal_pdf_fallback(proposal_data, invoice_data, commercial)
        
    try:
        # Calcular URL absoluta de la foto del asesor (con fallback)
        advisor_image_url = url_for('static', filename='img/LOGO-OLE-CONTULTING-COLOR.png', _external=True)
        if commercial:
            img_candidate = getattr(commercial, 'profile_image_url', None)
            if img_candidate:
                img = str(img_candidate)
                if img.startswith('http://') or img.startswith('https://') or img.startswith('data:'):
                    advisor_image_url = img
                elif img.startswith('/'):
                    advisor_image_url = urljoin(request.url_root, img.lstrip('/'))
                else:
                    advisor_image_url = urljoin(request.url_root, img)
            elif getattr(commercial, 'profile_image', None):
                img = str(commercial.profile_image)
                if img.startswith('http://') or img.startswith('https://') or img.startswith('data:'):
                    advisor_image_url = img
                elif img.startswith('/static/'):
                    advisor_image_url = urljoin(request.url_root, img.lstrip('/'))
                elif img.startswith('static/'):
                    advisor_image_url = urljoin(request.url_root, img)
                else:
                    from os.path import basename
                    advisor_image_url = url_for('static', filename=f'uploads/profiles/{basename(img)}', _external=True)

        # Preparar datos para la plantilla
        template_data = {
            'proposal_data': proposal_data,
            'invoice_data': invoice_data,
            'commercial': commercial,
            'current_date': datetime.now().strftime('%d/%m/%Y'),
            'advisor_image_url': advisor_image_url
        }
        
        # Renderizar la plantilla HTML
        html_content = render_template('Private_Invoice/propuesta_pdf_simple.html', **template_data)
        
        # Configuración para pdfkit
        options = {
            'page-size': 'A4',
            'margin-top': '0.75in',
            'margin-right': '0.75in',
            'margin-bottom': '0.75in',
            'margin-left': '0.75in',
            'encoding': "UTF-8",
            'no-outline': None,
            'enable-local-file-access': None
        }
        
        # Crear el PDF usando pdfkit
        pdf_data = pdfkit.from_string(html_content, False, options=options)
        
        # Crear buffer
        pdf_buffer = BytesIO()
        pdf_buffer.write(pdf_data)
        pdf_buffer.seek(0)
        
        return pdf_buffer
        
    except Exception as e:
        current_app.logger.error(f"Error generando PDF con pdfkit: {str(e)}")
        return generate_proposal_pdf_fallback(proposal_data, invoice_data, commercial)


def generate_proposal_pdf_fallback(proposal_data, invoice_data, commercial):
    """
    Método de fallback usando ReportLab si pdfkit no está disponible
    """
    from reportlab.lib.pagesizes import A4
    from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
    from reportlab.lib.units import cm
    from reportlab.lib.colors import HexColor
    from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
    from reportlab.lib.enums import TA_CENTER, TA_LEFT
    
    buffer = BytesIO()
    doc = SimpleDocTemplate(buffer, pagesize=A4, rightMargin=2*cm, leftMargin=2*cm, topMargin=2*cm, bottomMargin=2*cm)
    
    styles = getSampleStyleSheet()
    title_style = ParagraphStyle('CustomTitle', parent=styles['Heading1'], fontSize=18, textColor=HexColor('#0b99fd'), alignment=TA_CENTER, spaceAfter=20)
    
    story = []
    story.append(Paragraph("Propuesta Energética Personalizada", title_style))
    story.append(Spacer(1, 20))
    
    # Información básica
    if commercial:
        story.append(Paragraph(f"<b>Asesor:</b> {commercial.first_name} {commercial.last_name}", styles['Normal']))
        story.append(Paragraph(f"<b>Email:</b> {commercial.email}", styles['Normal']))
        story.append(Spacer(1, 10))
    
    story.append(Paragraph(f"<b>Cliente:</b> {invoice_data.get('client_name', 'N/A')}", styles['Normal']))
    story.append(Paragraph(f"<b>CUPS:</b> {invoice_data.get('cups', 'N/A')}", styles['Normal']))
    story.append(Spacer(1, 20))
    
    # Planes
    for i, plan in enumerate(proposal_data.get('selected_plans', []), 1):
        story.append(Paragraph(f"Plan {i}: {plan.get('tariff_name', 'N/A')}", styles['Heading2']))
        story.append(Paragraph(f"Ahorro anual: {plan.get('annual_savings', 0):.2f}€", styles['Normal']))
        story.append(Paragraph(f"Coste mensual: {plan.get('monthly_cost', 0):.2f}€", styles['Normal']))
        story.append(Spacer(1, 15))
    
    doc.build(story)
    buffer.seek(0)
    return buffer


def generate_proposal_pdf(proposal_data, invoice_data, commercial=None):
    """
    Función principal que intenta usar diferentes métodos para generar PDF
    según el entorno (servidor o local)
    """
    current_app.logger.info("Iniciando generación de PDF")
    
    # Detectar si estamos en un entorno de servidor
    server_env = is_server_environment()
    if server_env:
        current_app.logger.info("Detectado entorno de servidor, saltando Playwright")
    
    # En entorno local, intentar Playwright primero si está disponible
    if not server_env and PLAYWRIGHT_AVAILABLE:
        try:
            current_app.logger.info("Intentando generar PDF con Playwright")
            return generate_proposal_pdf_playwright(proposal_data, invoice_data, commercial)
        except Exception as e:
            current_app.logger.warning(f"Playwright falló, intentando WeasyPrint: {str(e)}")
    
    # Intentar WeasyPrint con importación diferida (funciona en servidor y local)
    try:
        current_app.logger.info("Intentando generar PDF con WeasyPrint")
        return generate_proposal_pdf_weasyprint(proposal_data, invoice_data, commercial)
    except Exception as e:
        current_app.logger.warning(f"WeasyPrint falló, intentando pdfkit: {str(e)}")
    
    # Intentar pdfkit (requiere wkhtmltopdf instalado)
    if PDFKIT_AVAILABLE:
        try:
            current_app.logger.info("Intentando generar PDF con pdfkit")
            return generate_proposal_pdf_pdfkit(proposal_data, invoice_data, commercial)
        except Exception as e:
            current_app.logger.warning(f"pdfkit falló, usando fallback: {str(e)}")
    
    # Último recurso: ReportLab (siempre disponible con pip)
    current_app.logger.info("Usando fallback ReportLab para generar PDF")
    return generate_proposal_pdf_fallback(proposal_data, invoice_data, commercial)


def create_proposal_filename(client_name):
    """Crea un nombre de archivo para la propuesta"""
    today = datetime.now().strftime('%Y%m%d')
    safe_client_name = "".join(c for c in client_name if c.isalnum() or c in (' ', '-', '_')).rstrip()
    safe_client_name = safe_client_name.replace(' ', '_')
    return f"Propuesta_Energetica_{safe_client_name}_{today}.pdf"
