import os
from server_backsemot.models import Qr, Despachador, Transaccion, QrWeb, TransaccionWeb, FotoCamion, QrPresencial, TicketPresencial, RegistroFacturacionPresencial, CertificadoPresencial
from rest_framework.decorators import api_view
from server_backsemot.api.clientewebValidaciones import validaciones_basicas_clienteweb
from server_backsemot.personal.despachador import validaciones_basicas_despachador, mantener_cliente_activo
from server_backsemot.personal.personal import validaciones_basicas, mantener_personal_activo
from server_backsemot.api.brevo import brevo_correo_pdf
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
from reportlab.lib.colors import Color
from PyPDF2 import PdfReader, PdfWriter
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm
from io import BytesIO
from django.conf import settings
from server_backsemot.utiles import *
import tempfile
import segno
import traceback
from html import escape
from reportlab.platypus import Paragraph
from reportlab.lib.styles import ParagraphStyle
from reportlab.pdfbase.pdfmetrics import registerFontFamily
from reportlab.lib.enums import TA_JUSTIFY



@api_view(["GET"])
def enviar_pdf_correo_admin_cliente(request):
    try:
        # Validación básica
        validacion = validaciones_basicas(validaciones=[1, 2, 3, 4], perfiles=[1, 2, 3], request=request)
        if validacion != "ok":
            return Utiles.responder_500(validacion)
        
        required_fields = ["ticket", "correo"]
        for field in required_fields:
            if field not in request.POST:
                return Utiles.responder_500(f"Falta {field}")
            
        correo = request.GET["correo"]
        if not Utiles.valida_email(correo):
            return Utiles.responder_500("Ingrese un correo válido")
        
        qr = Qr.objects.get(id=request.GET["ticket"])
        trans = Transaccion.objects.filter(qr=qr).first()
        if not trans:
            return Utiles.responder_500("No existe transacción asociada al ticket")
        
        variable = trans.pesaje

        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra.nombre,
            "camion": trans.camion.patente,
            "peso": trans.camion.cantidad,
            "medida": trans.camion.unidad.capitalize(),
            "emision": qr.fechaCreacion,  # Formato sin la hora
            "vencimiento": qr.fechaValidez,  # Formato sin la hora
            "variable": trans.camion.peso_variable,
            "ultimo_pesaje": variable.fecha if variable else None,
        }
        fotos = FotoCamion.objects.filter(camion=trans.camion).all().order_by("index")
        pdf = generar_pdf_con_qr(qr.codigoQr, datos, fotos)
        resp, text = brevo_correo_pdf(trans.cliente.nombre, correo, pdf)
        mantener_personal_activo(request.GET["token"])
        if resp:
            return Utiles.responder_200(text)
        else:
            return Utiles.responder_500(text)
    except Qr.DoesNotExist:
        return Utiles.responder_500("No existe ticket con ese id")
    except:
        return Utiles.responder_500("Error inesperado", sys.exc_info())
    


@api_view(["GET"])
def enviar_pdf_correo_admin_clienteweb(request):
    try:
        # Validación básica
        validacion = validaciones_basicas(validaciones=[1, 2, 3, 4], perfiles=[1, 2, 3], request=request)
        if validacion != "ok":
            return Utiles.responder_500(validacion)
        
        required_fields = ["ticket", "correo"]
        for field in required_fields:
            if field not in request.POST:
                return Utiles.responder_500(f"Falta {field}")
            
        correo = request.GET["correo"]
        if not Utiles.valida_email(correo):
            return Utiles.responder_500("Ingrese un correo válido")
        
        qr = QrWeb.objects.get(id=request.GET["ticket"])
        trans = TransaccionWeb.objects.filter(qr=qr).first()
        if not trans:
            return Utiles.responder_500("No existe transacción asociada al ticket")

        variable = trans.pesaje

        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra.nombre,
            "camion": trans.camion.patente,
            "peso": trans.camion.cantidad,
            "medida": trans.camion.unidad.capitalize(),
            "emision": qr.fechaCreacion,  # Formato sin la hora
            "vencimiento": qr.fechaValidez,  # Formato sin la hora
            "variable": trans.camion.peso_variable,
            "ultimo_pesaje": variable.fecha if variable else None,
        }
        fotos = FotoCamion.objects.filter(camion=trans.camion).all().order_by("index")
        pdf = generar_pdf_con_qr(qr.codigoQr, datos, fotos)
        resp, text = brevo_correo_pdf(trans.cliente.nombre, correo, pdf)
        mantener_personal_activo(request.GET["token"])
        if resp:
            return Utiles.responder_200(text)
        else:
            return Utiles.responder_500(text)
    except Qr.DoesNotExist:
        return Utiles.responder_500("No existe ticket con ese id")
    except:
        return Utiles.responder_500("Error inesperado", sys.exc_info())
    


@api_view(["GET"])
def enviar_pdf_correo_cliente(request):
    try:
        # Validación básica
        validacion = validaciones_basicas_despachador(validaciones=[1, 2, 3, 4], perfiles=[1000, 999, 998], request=request)
        if validacion != "ok":
            return Utiles.responder_500(validacion)
        
        required_fields = ["ticket", "correo"]
        for field in required_fields:
            if field not in request.POST:
                return Utiles.responder_500(f"Falta {field}")
            
        correo = request.GET["correo"]
        if not Utiles.valida_email(correo):
            return Utiles.responder_500("Ingrese un correo válido")
        
        qr = Qr.objects.get(id=request.GET["ticket"])
        trans = Transaccion.objects.filter(qr=qr).first()
        if not trans:
            return Utiles.responder_500("No existe transacción asociada al ticket")
        
        variable = trans.pesaje

        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra.nombre,
            "camion": trans.camion.patente,
            "peso": trans.camion.cantidad,
            "medida": trans.camion.unidad.capitalize(),
            "emision": qr.fechaCreacion,  # Formato sin la hora
            "vencimiento": qr.fechaValidez,  # Formato sin la hora
            "variable": trans.camion.peso_variable,
            "ultimo_pesaje": variable.fecha if variable else None,
        }
        fotos = FotoCamion.objects.filter(camion=trans.camion).all().order_by("index")
        pdf = generar_pdf_con_qr(qr.codigoQr, datos, fotos)
        resp, text = brevo_correo_pdf(trans.cliente.nombre, correo, pdf)
        mantener_cliente_activo(request.GET["token"])
        if resp:
            return Utiles.responder_200(text)
        else:
            return Utiles.responder_500(text)
    except Qr.DoesNotExist:
        return Utiles.responder_500("No existe ticket con ese id")
    except:
        return Utiles.responder_500("Error inesperado", sys.exc_info())



def enviar_pdf_correo_cliente_presencial(trans:TicketPresencial, correo):
    try:
        if not trans:
            return Utiles.responder_500("No existe transacción asociada al ticket")
        qr = trans.qr

        variable = trans.pesaje

        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra,
            "camion": trans.camion.patente,
            "peso": trans.cantidad,
            "medida": trans.unidad.capitalize(),
            "emision": trans.fecha_creacion.date(),  # Formato sin la hora
            "vencimiento": trans.fecha_creacion.date(),  # Formato sin la hora
            "lomo": "Si" if trans.lomo == 1 else "No",
            "precio": trans.total,
            "variable": trans.camion.peso_variable,
            "ultimo_pesaje": variable.fecha if variable else None,
        }

        rfp = RegistroFacturacionPresencial.objects.filter(ticket=trans).first()
        url = rfp.link if rfp and rfp.link else "#"
        pdf = generar_pdf_con_qr_presencial(qr.codigoQr, datos)
        resp, text = brevo_correo_pdf(trans.cliente.nombre, correo, pdf, url)
        return resp, text
    except Qr.DoesNotExist:
        return False, "No existe ticket con ese id"
    except:
        return False, "Error inesperado"
    


@api_view(["GET"])
def enviar_pdf_correo_clienteweb(request):
    try:
        # Validación básica
        validacion = validaciones_basicas_clienteweb(validaciones=[1, 2, 3, 4], perfiles=[499, 500], request=request)
        if validacion != "ok":
            return Utiles.responder_500(validacion)
        
        required_fields = ["ticket", "correo"]
        for field in required_fields:
            if field not in request.POST:
                return Utiles.responder_500(f"Falta {field}")
            
        correo = request.GET["correo"]
        if not Utiles.valida_email(correo):
            return Utiles.responder_500("Ingrese un correo válido")
        
        qr = QrWeb.objects.get(id=request.GET["ticket"])
        trans = TransaccionWeb.objects.filter(qr=qr).first()
        if not trans:
            return Utiles.responder_500("No existe transacción asociada al ticket")
        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra if trans.obra else "Particular",
            "camion": trans.camion,
            "peso": trans.cantidad,
            "medida": trans.unidad.capitalize(),
            "emision": qr.fechaCreacion,
            "vencimiento": qr.fechaValidez
        }
        fotos = FotoCamion.objects.filter(camion=trans.camion).all().order_by("index")
        pdf = generar_pdf_con_qr(qr.codigoQr, datos, fotos)
        resp, text = brevo_correo_pdf(trans.cliente.nombre, correo, pdf)
        if resp:
            return Utiles.responder_200(text)
        else:
            return Utiles.responder_500(text)
    except Qr.DoesNotExist:
        return Utiles.responder_500("No existe ticket con ese id")
    except:
        return Utiles.responder_500("Error inesperado", sys.exc_info())
    


def enviar_pdf_correo_clienteweb_interno(ticket, correo, url):
    try:
        qr = QrWeb.objects.get(id=ticket)
        trans = TransaccionWeb.objects.filter(qr=qr).first()
        if not trans:
            return Utiles.responder_500("No existe transacción asociada al ticket")
        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra if trans.obra else "Particular",
            "camion": trans.camion,
            "peso": trans.cantidad,
            "medida": trans.unidad.capitalize(),
            "emision": qr.fechaCreacion,
            "vencimiento": qr.fechaValidez
        }
        fotos = FotoCamion.objects.filter(camion=trans.camion).all().order_by("index")
        pdf = generar_pdf_con_qr(qr.codigoQr, datos, fotos)
        resp, text = brevo_correo_pdf(trans.cliente.nombre, correo, pdf, url)
        if resp:
            return True, text
        else:
            return False, text
    except Qr.DoesNotExist:
        return False, "No existe ticket con ese id"
    except:
        return False, "Error inesperado"



def generar_pdf_con_qr(qr_data, datos, fotos):
    try:
        # Crear buffer para QR
        packet = BytesIO()
        c = canvas.Canvas(packet, pagesize=A4)
        width, height = A4

        # QR
        qr = segno.make_qr(qr_data)
        with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_qr_file:
            qr.save(tmp_qr_file, kind='png', scale=10)
            tmp_qr_path = tmp_qr_file.name

        # Posición QR
        cuadro_x, cuadro_y = 298, 542
        cuadro_size = 10.77 * cm
        qr_size = 4.0 * cm
        margen_x = (cuadro_size - qr_size) / 2
        margen_y = (cuadro_size - qr_size) / 2
        qr_x = cuadro_x + margen_x
        qr_y = cuadro_y + margen_y

        # Añadir QR y texto
        c.drawImage(tmp_qr_path, qr_x, qr_y, width=qr_size, height=qr_size)
        c.setFont("Helvetica", 12)
        c.drawString(168, 745, f"{datos['cliente']}")
        c.drawString(168, 732, f"{datos['obra']}")
        c.drawString(168, 718, f"{datos['camion']}")
        c.drawString(168, 703, f"{datos['medida']}")
        c.drawString(168, 687, f"{datos['peso']}")
        c.drawString(168, 655, f"{invertir_fecha(datos['emision'])}")
        c.drawString(168, 638, f"{invertir_fecha(datos['vencimiento'])}")
        c.drawRightString(565, 787, f"{datos['orden']}")
        if datos['variable'] == 1:
            if datos['ultimo_pesaje'] is None:
                c.drawString(200, 672, f"0000-00-00")
            else:
                c.drawString(200, 672, f"{invertir_fecha_hora(datos['ultimo_pesaje'])}")

        c.showPage()
        c.save()
        packet.seek(0)

        qr_pdf = PdfReader(packet)
        if datos['variable'] == 1:
            plantilla_pdf_path = os.path.join(settings.MEDIA_ROOT, 'pdf', 'plantillaticketVariable.pdf')
        else:
            plantilla_pdf_path = os.path.join(settings.MEDIA_ROOT, 'pdf', 'plantillaticket.pdf')

        with open(plantilla_pdf_path, "rb") as plantilla_pdf_file:
            plantilla_pdf = PdfReader(plantilla_pdf_file)
            output_pdf = BytesIO()
            pdf_writer = PdfWriter()

            page = plantilla_pdf.pages[0]
            qr_page = qr_pdf.pages[0]
            page.merge_page(qr_page)
            pdf_writer.add_page(page)

            for i in range(1, len(plantilla_pdf.pages)):
                pdf_writer.add_page(plantilla_pdf.pages[i])

            pdf_writer.write(output_pdf)
            output_pdf.seek(0)

        # Agregar fotos del camión
        fotos_max = fotos[:3]
        foto_positions = [(30, 315), (210, 315), (389, 315)]
        foto_size = (176, 176)

        merged_pdf = PdfReader(output_pdf)
        merged_page = merged_pdf.pages[0]
        output_final = BytesIO()
        writer_final = PdfWriter()

        overlay_packet = BytesIO()
        overlay_canvas = canvas.Canvas(overlay_packet, pagesize=A4)

        for idx, foto_obj in enumerate(fotos_max):
            try:
                # Eliminar duplicado de "uploads/" si existe
                ruta_relativa = foto_obj.ruta.replace('uploads/', '', 1).lstrip('/')
                foto_abs_path = os.path.join(settings.MEDIA_ROOT, ruta_relativa)

                x, y = foto_positions[idx]
                overlay_canvas.drawImage(foto_abs_path, x, y, width=foto_size[0], height=foto_size[1], preserveAspectRatio=True, mask='auto')
            except Exception as e:
                traceback.print_exc()
                print(f"Error al insertar imagen {idx + 1}: {foto_obj.ruta} -> {e}")

        overlay_canvas.save()
        overlay_packet.seek(0)

        overlay_pdf = PdfReader(overlay_packet)
        if overlay_pdf.pages:
            merged_page.merge_page(overlay_pdf.pages[0])

        writer_final.add_page(merged_page)
        writer_final.write(output_final)
        output_final.seek(0)

        os.remove(tmp_qr_path)
        return output_final

    except Exception as e:
        traceback.print_exc()
        return None



def generar_pdf_con_certificado(cert, tipo):
    try:
        registrar_fuentes_pdf()

        packet = BytesIO()
        c = canvas.Canvas(packet, pagesize=A4)


        if tipo == 1:
            cliente_nombre = escape(cert.cliente.nombre)
            cliente_rut = escape(cert.cliente.rut)
            if cert.rut_constructora and cert.nombre_constructora:
                constructora_nombre = escape(cert.nombre_constructora)
                constructora_rut = escape(cert.rut_constructora)
            elif cert.obra.rut and cert.obra.constructora:
                constructora_nombre = escape(cert.obra.constructora)
                constructora_rut = escape(cert.obra.rut)
            else:
                constructora_nombre = escape(cert.cliente.nombre)
                constructora_rut = escape(cert.cliente.rut)
        else:
            cliente_nombre = escape(cert.cliente.nombre)
            cliente_rut = escape(cert.cliente.rut)
            if cert.rut_constructora and cert.nombre_constructora:
                constructora_nombre = escape(cert.nombre_constructora)
                constructora_rut = escape(cert.rut_constructora)
            else:
                constructora_nombre = escape(cert.cliente.nombre)
                constructora_rut = escape(cert.cliente.rut)

        fecha_desde = fmt_fecha(cert.fecha_desde)
        fecha_hasta = fmt_fecha(cert.fecha_hasta)

        total_m3 = escape(str(cert.total_m3))
        total_toneladas = escape(str(cert.total_toneladas))

        fecha_emision = fmt_fecha(cert.fecha_aprobacion)

        if tipo == 1:
            obra_nombre = escape(cert.obra.nombre)
            obra_direccion = escape(cert.obra.direccion)
            obra_comuna = escape(cert.obra.comuna.nombreComuna)
        else:
            obra_nombre = escape(cert.obra) if cert.obra else None
            obra_direccion = escape(cert.direccion) if cert.direccion else None
            obra_comuna = escape(cert.comuna.nombreComuna) if cert.comuna and cert.comuna.nombreComuna else None
        
        # QR
        url_validacion = "https://semot.cl/validarcertificado"
        qr = segno.make_qr(url_validacion)

        with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_qr_file:
            qr.save(
                tmp_qr_file,
                kind="png",
                scale=10,
                dark="black",
                light=None,
                border=0
            )
            tmp_qr_path = tmp_qr_file.name

        # Posición QR
        qr_size = 2.5 * cm

        # Ajusta estas coordenadas según el cuadro del PDF
        qr_x = 155
        qr_y = 160

        c.drawImage(
            tmp_qr_path,
            qr_x,
            qr_y,
            width=qr_size,
            height=qr_size,
            mask="auto"
        )

        # Número certificado y fecha
        c.setFont("HVBold", 11)
        c.drawRightString(500, 714, f"N° Certificado: {cert.id}")

        c.setFont("HV", 11)
        c.drawRightString(500, 700, f"Santiago, {fecha_emision}")

        x = 82
        width = 430
        y = 600

        if cert.total_m3 > 0  and cert.total_toneladas > 0:
            parrafo_1 = f"""
            Por medio de la presente, certificamos que recibimos de parte de
            <b>{cliente_nombre}</b>, RUT: <b>{cliente_rut}</b>, desde el
            <b>{fecha_desde}</b> al <b>{fecha_hasta}</b>, la cantidad de
            <b>{formato_chileno(total_m3)} m³</b> y de <b>{formato_chileno(total_toneladas)} toneladas de ESCOMBROS INERTES</b>
            para recuperación de pozo SEMOT LTDA. R.U.T. 83.853.800-2 ubicado en calle
            Elisa Correa N° 3936, comuna de Puente Alto, Resolución 000271 del
            Servicio de Salud del Ambiente de la Región Metropolitana.
            """.strip()
        elif cert.total_m3 > 0 and cert.total_toneladas <= 0:
            parrafo_1 = f"""
            Por medio de la presente, certificamos que recibimos de parte de
            <b>{cliente_nombre}</b>, RUT: <b>{cliente_rut}</b>, desde el
            <b>{fecha_desde}</b> al <b>{fecha_hasta}</b>, la cantidad de
            <b>{formato_chileno(total_m3)} m³ de ESCOMBROS INERTES</b>
            para recuperación de pozo SEMOT LTDA. R.U.T. 83.853.800-2 ubicado en calle
            Elisa Correa N° 3936, comuna de Puente Alto, Resolución 000271 del
            Servicio de Salud del Ambiente de la Región Metropolitana.
            """.strip()
        elif cert.total_m3 <= 0 and cert.total_toneladas > 0:
            parrafo_1 = f"""
            Por medio de la presente, certificamos que recibimos de parte de
            <b>{cliente_nombre}</b>, RUT: <b>{cliente_rut}</b>, desde el
            <b>{fecha_desde}</b> al <b>{fecha_hasta}</b>, la cantidad de
            <b>{formato_chileno(total_toneladas)} toneladas de ESCOMBROS INERTES</b>
            para recuperación de pozo SEMOT LTDA. R.U.T. 83.853.800-2 ubicado en calle
            Elisa Correa N° 3936, comuna de Puente Alto, Resolución 000271 del
            Servicio de Salud del Ambiente de la Región Metropolitana.
            """.strip()
        else:
            return False, "No existe cantidad mínima para generar un certificado"

        y = draw_paragraph(c, parrafo_1, x, y, width, font_size=13, leading=15)

        y -= 22

        if obra_direccion and obra_nombre:
            parrafo_2 = f"""
            El Cliente <b>{cliente_nombre}</b>, RUT <b>{cliente_rut}</b>, declara que
            el escombro inerte proviene de la obra <b>{obra_nombre}</b>
            """
            parrafo_2 += f""", ubicada en <b>{obra_direccion}</b>"""

            if obra_comuna:
                parrafo_2 += f""" de la comuna de <b>{obra_comuna}</b>."""

            y = draw_paragraph(c, parrafo_2, x, y, width, font_size=13, leading=15)

            y -= 22

        parrafo_3 = f"""
        El presente certificado se extiende a petición de la empresa interesada,
        para ser presentado ante la empresa <b>{constructora_nombre}</b>
        RUT: <b>{constructora_rut}</b>.
        """

        y = draw_paragraph(c, parrafo_3, x, y, width, font_size=13, leading=15)

        y -= 22

        draw_paragraph(
            c,
            "Sin más que agregar,",
            x,
            y,
            width,
            font_size=13,
            leading=15
        )

        # Texto QR / código, solo como placeholder por ahora
        c.setFont("HVBold", 24)
        c.drawString(240, 176, str(cert.codigo_validacion or ""))

        c.showPage()
        c.save()
        packet.seek(0)

        overlay_pdf = PdfReader(packet)

        plantilla_pdf_path = os.path.join(
            settings.MEDIA_ROOT,
            "pdf",
            "plantillaCertificado.pdf"
        )

        with open(plantilla_pdf_path, "rb") as plantilla_pdf_file:
            plantilla_pdf = PdfReader(plantilla_pdf_file)
            writer = PdfWriter()

            page = plantilla_pdf.pages[0]
            page.merge_page(overlay_pdf.pages[0])
            writer.add_page(page)

            output_final = BytesIO()
            writer.write(output_final)
            output_final.seek(0)

        if os.path.exists(tmp_qr_path):
            os.remove(tmp_qr_path)

        return True, output_final

    except Exception:
        traceback.print_exc()
        return None



def formato_chileno(valor):
    if valor is None:
        return ""

    texto = str(valor)

    if "." in texto:
        entero, decimal = texto.split(".", 1)
    else:
        entero, decimal = texto, None

    entero = f"{int(entero):,}".replace(",", ".")

    if decimal is not None:
        return f"{entero},{decimal}"

    return entero



def fmt_fecha(fecha):
    try:
        if not fecha:
            return ""

        meses = [
            "enero", "febrero", "marzo", "abril", "mayo", "junio",
            "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"
        ]

        return f"{fecha.day:02d} de {meses[fecha.month - 1]} de {fecha.year}"
    except Exception:
        traceback.print_exc()


def draw_paragraph(c, text, x, y, width, font_size=13, leading=15, align=0):
    try:
        style = ParagraphStyle(
            name="Custom",
            fontName="HV",
            fontSize=font_size,
            leading=leading,
            alignment=TA_JUSTIFY,
        )

        p = Paragraph(text, style)
        _, h = p.wrap(width, 500)
        p.drawOn(c, x, y - h)

        return y - h
    except Exception:
        traceback.print_exc()



def generar_pdf_con_qr_presencial(qr_data, datos):
    try:
        # Crear buffer para QR
        packet = BytesIO()
        c = canvas.Canvas(packet, pagesize=A4)
        width, height = A4

        # QR
        qr = segno.make_qr(qr_data)
        with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_qr_file:
            qr.save(tmp_qr_file, kind='png', scale=10)
            tmp_qr_path = tmp_qr_file.name

        # Posición QR
        cuadro_x, cuadro_y = 290, 480
        cuadro_size = 11.77 * cm
        qr_size = 7.0 * cm
        margen_x = (cuadro_size - qr_size) / 2
        margen_y = (cuadro_size - qr_size) / 2
        qr_x = cuadro_x + margen_x
        qr_y = cuadro_y + margen_y

        # Añadir QR y texto
        c.drawImage(tmp_qr_path, qr_x, qr_y, width=qr_size, height=qr_size)
        c.setFont("Helvetica", 12)
        c.drawString(168, 747, f"{datos['cliente']}")
        c.drawString(168, 695, f"{datos['obra']}")
        c.drawString(168, 617, f"{datos['camion']}")
        c.drawString(168, 603, f"{datos['medida']}")
        c.drawString(168, 587, f"{datos['peso']}")
        c.drawString(168, 573, f"{datos['lomo']}")
        c.drawString(168, 554, f"{invertir_fecha(datos['emision'])}")
        c.drawString(168, 537, f"{invertir_fecha(datos['vencimiento'])}")
        precio_formateado = formatear_precio_chileno(float(datos['precio']))
        # Definir color personalizado (hex #4fa937 → RGB)
        color_verde = Color(red=0x4f/255, green=0xa9/255, blue=0x37/255)

        # Establecer fuente y color personalizados para el precio
        c.setFont("Helvetica-Bold", 23.7856)
        c.setFillColor(color_verde)
        c.drawRightString(244, 475, precio_formateado)

        # Restaurar fuente y color estándar 
        c.setFont("Helvetica", 12)
        c.setFillColorRGB(0, 0, 0)  # Negro
        c.drawRightString(565, 787, f"{datos['orden']}")

        # En caso que sea camión de peso variable
        if datos['variable'] == 1:
            if datos['ultimo_pesaje'] is None:
                c.drawString(195, 443, f"0000-00-00")
            else:
                c.drawString(195, 443, f"{invertir_fecha_hora(datos['ultimo_pesaje'])}")

        c.showPage()
        c.save()
        packet.seek(0)

        qr_pdf = PdfReader(packet)
        if datos['variable'] == 1:
            plantilla_pdf_path = os.path.join(settings.MEDIA_ROOT, 'pdf', 'plantillaticketPresencialVariable.pdf')
        else:
            plantilla_pdf_path = os.path.join(settings.MEDIA_ROOT, 'pdf', 'plantillaticketPresencial.pdf')

        with open(plantilla_pdf_path, "rb") as plantilla_pdf_file:
            plantilla_pdf = PdfReader(plantilla_pdf_file)
            output_pdf = BytesIO()
            pdf_writer = PdfWriter()

            page = plantilla_pdf.pages[0]
            qr_page = qr_pdf.pages[0]
            page.merge_page(qr_page)
            pdf_writer.add_page(page)

            for i in range(1, len(plantilla_pdf.pages)):
                pdf_writer.add_page(plantilla_pdf.pages[i])

            pdf_writer.write(output_pdf)
            output_pdf.seek(0)

        os.remove(tmp_qr_path)
        return output_pdf

    except Exception as e:
        traceback.print_exc()
        return None



@api_view(["GET"])
def ver_pdf_clientes(request):
    try:
        # Validación básica
        validacion = validaciones_basicas_despachador(validaciones=[1, 2, 3, 4], perfiles=[1000, 999, 998], request=request)
        if validacion != "ok":
            return Utiles.responder_500(validacion)
        
        if not "pdf" in request.GET:
            return Utiles.responder_500("Falta el código del pdf")
        
        token = request.GET["token"]
        id = request.GET["pdf"]
        desp = Despachador.objects.filter(token=token).first()
        if not desp:
            return Utiles.responder_500("No existe usuario con ese token")
        
        qr = Qr.objects.get(id=id)
        trans = Transaccion.objects.filter(qr=qr).first()
        if not trans:
            return Utiles.responder_500("noexiste")
        
        if trans.cliente.id != desp.cliente.id:
            return Utiles.responder_500("sinpermiso")
        
        variable = trans.pesaje

        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra.nombre,
            "camion": trans.camion.patente,
            "peso": trans.cantidad,
            "medida": trans.unidad,
            "emision": qr.fechaCreacion.strftime("%Y-%m-%d"),  # Formato sin la hora
            "vencimiento": qr.fechaValidez.strftime("%Y-%m-%d"),  # Formato sin la hora
            "variable": trans.camion.peso_variable,
            "ultimo_pesaje": variable.fecha if variable else None,
        }
        fotos = FotoCamion.objects.filter(camion=trans.camion).all().order_by("index")
        pdf = generar_pdf_con_qr(qr.codigoQr, datos, fotos)
        mantener_cliente_activo(request.GET["token"])
        return Utiles.responder_200_archivo(pdf, "ticket" + str(qr.id) + ".pdf")

    except Qr.DoesNotExist:
        return Utiles.responder_500("noexiste")
    except:
        return Utiles.responder_500("Error", sys.exc_info())
    


@api_view(["GET"])
def ver_pdf_clienteweb(request):
    try:
        # Validación básica
        validacion = validaciones_basicas_clienteweb(validaciones=[1], request=request)
        if validacion != "ok":
            return Utiles.responder_500(validacion)
        
        if not "pdf" in request.GET:
            return Utiles.responder_500("Falta el código del pdf")
        
        if not "token" in request.GET:
            return Utiles.responder_500("Falta el token")
        
        token = request.GET["token"]
        id = request.GET["pdf"]
        
        qr = QrWeb.objects.filter(id=id, token__iexact=token).first()
        if not qr:
            return Utiles.responder_200("No existe el ticket")
        
        trans = TransaccionWeb.objects.filter(qr=qr).first()
        if not trans:
            return Utiles.responder_500("No existe el ticket indicado")
        
        
        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra if trans.obra else "Particular",
            "camion": trans.camion,
            "peso": trans.cantidad,
            "medida": trans.unidad,
            "emision": qr.fechaCreacion.strftime("%Y-%m-%d"),  # Formato sin la hora
            "vencimiento": qr.fechaValidez.strftime("%Y-%m-%d")  # Formato sin la hora
        }
        fotos = FotoCamion.objects.filter(camion=trans.camion).all().order_by("index")
        pdf = generar_pdf_con_qr(qr.codigoQr, datos, fotos)
        return Utiles.responder_200_archivo(pdf, "ticket" + str(qr.id) + ".pdf")

    except:
        return Utiles.responder_500("Error", sys.exc_info())



@api_view(["GET"])
def ver_pdf_clientepresencial(request):
    try:
        # Validación básica
        validacion = validaciones_basicas(validaciones=[1, 2, 3, 4], perfiles=[1, 2, 3], request=request)
        if validacion != "ok":
            return Utiles.responder_500(validacion)
        
        if not "pdf" in request.GET:
            return Utiles.responder_500("Falta el código del pdf")
        
        id = request.GET["pdf"]
        
        qr = QrPresencial.objects.filter(id=id).first()
        if not qr:
            return Utiles.responder_200("No existe el ticket")
        
        trans = TicketPresencial.objects.filter(qr=qr).first()
        if not trans:
            return Utiles.responder_500("No existe el ticket indicado")
        
        variable = trans.pesaje
        
        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra if trans.obra else "Particular",
            "camion": trans.camion.patente,
            "peso": trans.cantidad,
            "medida": trans.unidad,
            "emision": qr.fechaCreacion.strftime("%Y-%m-%d"),  # Formato sin la hora
            "vencimiento": qr.fechaValidez.strftime("%Y-%m-%d"),  # Formato sin la hora
            "precio": trans.total,
            "lomo": "Sí" if trans.lomo == 1 else "No",
            "variable": trans.camion.peso_variable,
            "ultimo_pesaje": variable.fecha if variable else None,
        }
        pdf = generar_pdf_con_qr_presencial(qr.codigoQr, datos)
        return Utiles.responder_200_archivo(pdf, "ticket" + str(qr.id) + ".pdf")

    except:
        traceback.print_exc()
        return Utiles.responder_500("Error", sys.exc_info())



@api_view(["GET"])
def ver_pdf_admin(request):
    try:
        # Validación básica
        validacion = validaciones_basicas(validaciones=[1, 2, 3, 4], perfiles=[1, 2, 3], request=request)
        if validacion != "ok":
            return Utiles.responder_500(validacion)
        
        if not "pdf" in request.GET:
            return Utiles.responder_500("Falta el código del pdf")
        
        id = request.GET["pdf"]
        
        qr = Qr.objects.get(id=id)
        trans = Transaccion.objects.filter(qr=qr).first()
        if not trans:
            return Utiles.responder_500("noexiste")
        
        variable = trans.pesaje
        
        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra.nombre,
            "camion": trans.camion.patente,
            "peso": trans.cantidad,
            "medida": trans.unidad,
            "emision": qr.fechaCreacion.strftime("%Y-%m-%d"),  # Formato sin la hora
            "vencimiento": qr.fechaValidez.strftime("%Y-%m-%d"),  # Formato sin la hora
            "variable": trans.camion.peso_variable,
            "ultimo_pesaje": variable.fecha if variable else None,
        }
        fotos = FotoCamion.objects.filter(camion=trans.camion).all().order_by("index")
        pdf = generar_pdf_con_qr(qr.codigoQr, datos, fotos)
        mantener_personal_activo(request.GET["token"])
        return Utiles.responder_200_archivo(pdf, "ticket" + str(qr.id) + ".pdf")

    except Qr.DoesNotExist:
        return Utiles.responder_500("noexiste")
    except:
        traceback.print_exc()
        return Utiles.responder_500("Error", sys.exc_info())
    


@api_view(["GET"])
def ver_pdfweb_admin(request):
    try:
        # Validación básica
        validacion = validaciones_basicas(validaciones=[1, 2, 3, 4], perfiles=[1, 2, 3], request=request)
        if validacion != "ok":
            return Utiles.responder_500(validacion)
        
        if not "pdf" in request.GET:
            return Utiles.responder_500("Falta el código del pdf")
        
        id = request.GET["pdf"]
        
        qr = QrWeb.objects.get(id=id)
        trans = TransaccionWeb.objects.filter(qr=qr).first()
        if not trans:
            return Utiles.responder_500("noexiste")
        
        datos = {
            "orden": f"{trans.id}",
            "cliente": trans.cliente.nombre,
            "obra": trans.obra if trans.obra else "Particular",
            "camion": trans.camion,
            "peso": trans.cantidad,
            "medida": trans.unidad.capitalize(),
            "emision": qr.fechaCreacion.strftime("%Y-%m-%d"),  # Formato sin la hora
            "vencimiento": qr.fechaValidez.strftime("%Y-%m-%d")  # Formato sin la hora
        }
        fotos = FotoCamion.objects.filter(camion=trans.camion).all().order_by("index")
        pdf = generar_pdf_con_qr(qr.codigoQr, datos, fotos)
        mantener_personal_activo(request.GET["token"])
        return Utiles.responder_200_archivo(pdf, "ticket" + str(qr.id) + ".pdf")

    except QrWeb.DoesNotExist:
        return Utiles.responder_500("noexiste")
    except:
        return Utiles.responder_500("Error", sys.exc_info())



def invertir_fecha(fecha_input):
    # Si la fecha es un objeto datetime o date, convertirla a string en formato YYYY-MM-DD
    if isinstance(fecha_input, datetime):
        fecha_str = fecha_input.strftime("%Y-%m-%d %H:%M:%S")  # Convertimos datetime a string
    elif isinstance(fecha_input, date):
        fecha_str = fecha_input.strftime("%Y-%m-%d")  # Convertimos date a string
    else:
        fecha_str = str(fecha_input)  # Si ya es string, lo dejamos así

    # Intentar parsear con formato que incluye hora
    try:
        fecha = datetime.strptime(fecha_str, "%Y-%m-%d %H:%M:%S")
    except ValueError:
        # Si falla, intentar con formato solo de fecha
        fecha = datetime.strptime(fecha_str, "%Y-%m-%d")

    # Formatear la fecha a dd-mm-aaaa y devolverla
    return fecha.strftime("%d-%m-%Y")



def invertir_fecha_hora(fecha_input): 
    if isinstance(fecha_input, datetime): 
        fecha_str = fecha_input.strftime("%Y-%m-%d %H:%M:%S") 
    elif isinstance(fecha_input, date): 
        fecha_str = fecha_input.strftime("%Y-%m-%d") 
    else: 
        fecha_str = str(fecha_input) 
    
    try: 
        fecha = datetime.strptime(fecha_str, "%Y-%m-%d %H:%M:%S") 
    except ValueError: 
        fecha = datetime.strptime(fecha_str, "%Y-%m-%d") 

    return fecha.strftime("%d-%m-%Y %H:%M:%S")



def formatear_precio_chileno(valor):
    try:
        valor = float(valor)
        return f"$ {int(valor):,}".replace(",", ".")
    except (ValueError, TypeError):
        return "$ 0"



def registrar_fuentes_pdf():
    FONT_DIR = os.path.join(settings.BASE_DIR, "uploads", "fonts")

    pdfmetrics.registerFont(TTFont("HV", os.path.join(FONT_DIR, "HelveticaNeueLTStd-Cn.ttf")))
    pdfmetrics.registerFont(TTFont("HVBold", os.path.join(FONT_DIR, "HelveticaNeueLTStd-HvCn.ttf")))

    registerFontFamily(
        "HV",
        normal="HV",
        bold="HVBold",
        italic="HV",
        boldItalic="HVBold"
    )