import sys
import json
import numpy as np
from reportlab.lib.pagesizes import letter, landscape
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable
)
from reportlab.pdfgen import canvas
from reportlab.graphics.shapes import Drawing, Rect, Line, String, PolyLine

class NumberedCanvas(canvas.Canvas):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._saved_page_states = []

    def showPage(self):
        self._saved_page_states.append(dict(self.__dict__))
        self._startPage()

    def save(self):
        num_pages = len(self._saved_page_states)
        for state in self._saved_page_states:
            self.__dict__.update(state)
            self.draw_page_decorations(num_pages)
            super().showPage()
        super().save()

    def draw_page_decorations(self, page_count):
        self.saveState()
        self.setFont("Helvetica", 7.5)
        self.setFillColor(colors.HexColor("#4A5568"))
        
        # Header
        self.drawString(40, 580, "Brana Projetos Navais | Plano de Linhas & Tabela de Cotas 2D — Casco Quinado 12m")
        self.drawRightString(752, 580, "Projetista: Aristides Cheto")
        self.setStrokeColor(colors.HexColor("#CBD5E0"))
        self.setLineWidth(0.5)
        self.line(40, 574, 752, 574)
            
        # Footer
        self.setStrokeColor(colors.HexColor("#CBD5E0"))
        self.setLineWidth(0.5)
        self.line(40, 30, 752, 30)
        
        footer_text = f"Página {self._pageNumber} de {page_count}"
        self.drawRightString(752, 20, footer_text)
        self.drawString(40, 20, "Estaleiro Escola Embrião (EEE Salvador) | Escola de Arquitetura e Engenharia Naval")
        self.restoreState()

def eval_hermite(P, t_global):
    n = len(P)
    if t_global <= P[0][0]:
        return P[0][1]
    if t_global >= P[-1][0]:
        return P[-1][1]
    for i in range(n - 1):
        x0, y0, m0 = P[i]
        x1, y1, m1 = P[i+1]
        if x0 <= t_global <= x1:
            dx = x1 - x0
            t = (t_global - x0) / dx
            h00 = 2*t**3 - 3*t**2 + 1
            h10 = t**3 - 2*t**2 + t
            h01 = -2*t**3 + 3*t**2
            h11 = t**3 - t**2
            return h00*y0 + h10*dx*m0 + h01*y1 + h11*dx*m1
    return P[-1][1]

def build_pdf(filename):
    proj_path = '/home/magdalena/eee/alunos/aristides-cheto/projeto.json'
    with open(proj_path, 'r', encoding='utf-8') as f:
        proj = json.load(f)

    # Document in Landscape (792 x 612 pt)
    doc = SimpleDocTemplate(
        filename,
        pagesize=landscape(letter),
        leftMargin=40,
        rightMargin=40,
        topMargin=42,
        bottomMargin=36
    )

    styles = getSampleStyleSheet()

    primary_color = colors.HexColor("#1A365D")   # Deep Navy
    secondary_color = colors.HexColor("#2B6CB0") # Marine Blue
    dark_text = colors.HexColor("#2D3748")
    light_bg = colors.HexColor("#F7FAFC")

    title_style = ParagraphStyle(
        'DocTitle', parent=styles['Heading1'],
        fontName='Helvetica-Bold', fontSize=15, leading=18, textColor=primary_color, spaceAfter=1
    )

    subtitle_style = ParagraphStyle(
        'DocSubtitle', parent=styles['Normal'],
        fontName='Helvetica', fontSize=8.5, leading=11, textColor=secondary_color, spaceAfter=4
    )

    h1_style = ParagraphStyle(
        'SectionH1', parent=styles['Heading2'],
        fontName='Helvetica-Bold', fontSize=9, leading=11, textColor=primary_color, spaceBefore=4, spaceAfter=3, keepWithNext=True
    )

    body_style = ParagraphStyle(
        'BodyDark', parent=styles['Normal'],
        fontName='Helvetica', fontSize=7.5, leading=9.5, textColor=dark_text, spaceAfter=2
    )

    table_cell = ParagraphStyle(
        'TableCell', parent=styles['Normal'],
        fontName='Helvetica', fontSize=7, leading=8.5, textColor=dark_text, alignment=1
    )

    table_header = ParagraphStyle(
        'TableHeader', parent=styles['Normal'],
        fontName='Helvetica-Bold', fontSize=7, leading=8.5, textColor=colors.white, alignment=1
    )

    story = []

    # Title & Subtitle
    story.append(Paragraph("PLANO DE LINHAS & TABELA DE COTAS 2D (BRANA)", title_style))
    story.append(Paragraph("Digitalização e Reconstrução Paramétrica | Casco Quinado (LOA 12,00 m · Boca 3,63 m · Pontal 1,78 m · $C_M = 0{,}75$)", subtitle_style))
    story.append(HRFlowable(width="100%", thickness=1.0, color=primary_color, spaceAfter=4))

    # Meta Info Row (Compact Table)
    info_data = [
        [Paragraph("<b>Projetista:</b> Aristides Cheto", table_cell),
         Paragraph("<b>Instituição:</b> Brana / EEE Salvador", table_cell),
         Paragraph("<b>Escala:</b> 0,50 m/qd (24 qd)", table_cell),
         Paragraph("<b>LOA:</b> 12,00 m", table_cell),
         Paragraph("<b>Boca:</b> 3,63 m", table_cell),
         Paragraph("<b>Pontal:</b> 1,78 m", table_cell),
         Paragraph("<b>$C_M$:</b> 0,75 (36/48)", table_cell)]
    ]
    info_table = Table(info_data, colWidths=[110, 110, 100, 72, 72, 72, 176])
    info_table.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), colors.HexColor("#EDF2F7")),
        ('BOX', (0,0), (-1,-1), 0.5, colors.HexColor("#CBD5E0")),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 2),
        ('BOTTOMPADDING', (0,0), (-1,-1), 2),
    ]))
    story.append(info_table)
    story.append(Spacer(1, 4))

    # Drawing Graphic (Vistas: Perfil, Planta, Balizas)
    # Total width: 712, height: 245
    dwg = Drawing(712, 245)
    dwg.add(Rect(0, 0, 712, 245, fillColor=colors.HexColor("#F8FAFC"), strokeColor=colors.HexColor("#CBD5E0"), strokeWidth=0.5))

    # Grid lines for stations (0 to 24 sq)
    # x goes 0 to 24 sq -> px: 40 to 480 (width = 440 px, scale_x = 18.33 px/sq)
    for sq_x in range(0, 25, 2):
        px = 40 + sq_x * (440/24)
        dwg.add(Line(px, 15, px, 230, strokeColor=colors.HexColor("#E2E8F0"), strokeWidth=0.5))
        st_num = sq_x // 2
        dwg.add(String(px, 6, f"B{st_num}", fontName="Helvetica", fontSize=6, fillColor=colors.HexColor("#718096"), textAnchor="middle"))

    # Labels
    dwg.add(String(45, 232, "PLANO DE PERFIL (SIDE VIEW)", fontName="Helvetica-Bold", fontSize=7.5, fillColor=primary_color))
    dwg.add(String(45, 112, "PLANO DE LINHAS D'ÁGUA / PLANTA (TOP VIEW)", fontName="Helvetica-Bold", fontSize=7.5, fillColor=primary_color))
    dwg.add(String(595, 232, "SEÇÃO MESTRA & BALIZAS", fontName="Helvetica-Bold", fontSize=7.5, fillColor=primary_color, textAnchor="middle"))

    curvas = proj['curvas']
    x_vals = np.linspace(0, 24, 100)
    
    prof_sheer_pts = []
    prof_chine_pts = []
    prof_keel_pts = []
    plan_sheer_pts = []
    plan_chine_pts = []

    for x in x_vals:
        px = 40 + x * (440/24)
        
        # Profile (Z above baseline y=140)
        zs = eval_hermite(curvas['profSheer'], x)
        zc = eval_hermite(curvas['profChine'], x)
        zk = eval_hermite(curvas['profKeel'], x)
        prof_sheer_pts.append((px, 140 + zs * 15))
        prof_chine_pts.append((px, 140 + zc * 15))
        prof_keel_pts.append((px, 140 + zk * 15))
        
        # Plan (Y around centerline y=60)
        ys = eval_hermite(curvas['planSheer'], x)
        yc = eval_hermite(curvas['planChine'], x)
        plan_sheer_pts.append((px, 60 + ys * 13))
        plan_chine_pts.append((px, 60 + yc * 13))

    # Base & Centerlines
    dwg.add(Line(40, 140, 480, 140, strokeColor=colors.HexColor("#A0AEC0"), strokeWidth=0.8, strokeDashArray=[2,2]))
    dwg.add(Line(40, 60, 480, 60, strokeColor=colors.HexColor("#A0AEC0"), strokeWidth=0.8, strokeDashArray=[2,2]))

    def add_poly(pts, color, width=1.2, dash=None):
        flat = [c for pt in pts for c in pt]
        dwg.add(PolyLine(flat, strokeColor=color, strokeWidth=width, strokeDashArray=dash))

    # Profile Curves
    add_poly(prof_sheer_pts, primary_color, 1.2)
    add_poly(prof_chine_pts, secondary_color, 1.0)
    add_poly(prof_keel_pts, colors.HexColor("#2D3748"), 1.2)

    # Plan Curves
    add_poly(plan_sheer_pts, primary_color, 1.2)
    add_poly(plan_chine_pts, secondary_color, 1.0)
    plan_sheer_mirror = [(p[0], 60 - (p[1]-60)) for p in plan_sheer_pts]
    plan_chine_mirror = [(p[0], 60 - (p[1]-60)) for p in plan_chine_pts]
    add_poly(plan_sheer_mirror, primary_color, 1.2)
    add_poly(plan_chine_mirror, secondary_color, 1.0)

    # Body Plan (Balizas Transversais)
    bx0, by0 = 595, 55
    dwg.add(Line(bx0, 35, bx0, 220, strokeColor=colors.HexColor("#A0AEC0"), strokeWidth=0.8, strokeDashArray=[2,2])) # Centerline
    dwg.add(Line(bx0 - 80, by0, bx0 + 80, by0, strokeColor=colors.HexColor("#A0AEC0"), strokeWidth=0.8)) # Baseline

    baliza_x = np.linspace(0, 24, 11)
    for idx, bx in enumerate(baliza_x):
        ys = eval_hermite(curvas['planSheer'], bx) * 18
        yc = eval_hermite(curvas['planChine'], bx) * 18
        zs = eval_hermite(curvas['profSheer'], bx) * 24
        zc = eval_hermite(curvas['profChine'], bx) * 24
        zk = eval_hermite(curvas['profKeel'], bx) * 24

        side = 1 if bx >= 12 else -1
        col = colors.HexColor("#3182CE") if bx == 10 or bx == 12 else colors.HexColor("#4A5568")
        w = 1.4 if bx == 10 or bx == 12 else 0.75
        
        poly_pts = [
            bx0, by0 + zk,
            bx0 + side * yc, by0 + zc,
            bx0 + side * ys, by0 + zs
        ]
        dwg.add(PolyLine(poly_pts, strokeColor=col, strokeWidth=w))

    dwg.add(String(bx0 - 45, 42, "← RÉ (B0 a B5)", fontName="Helvetica", fontSize=6, fillColor=colors.HexColor("#718096")))
    dwg.add(String(bx0 + 45, 42, "VANTE (B6 a B10) →", fontName="Helvetica", fontSize=6, fillColor=colors.HexColor("#718096"), textAnchor="end"))

    story.append(dwg)
    story.append(Spacer(1, 4))

    # Tabela de Cotas
    story.append(Paragraph("TABELA DE COTAS (OFFSETS) — 11 ESTAÇÕES LONGITUDINAIS [mm]", h1_style))
    
    headers = ["Cota / Estação"] + [f"B{i} ({i*1.2:.1f}m)" for i in range(11)]
    
    row_y_sheer = ["Meia-Boca Borda (Y)"]
    row_y_chine = ["Meia-Boca Chine (Y)"]
    row_z_sheer = ["Altura Borda (Z)"]
    row_z_chine = ["Altura Chine (Z)"]
    row_z_keel  = ["Altura Quilha (Z)"]
    row_v_angle = ["Ângulo de Deadrise (V)"]

    for i, bx in enumerate(baliza_x):
        ys_mm = eval_hermite(curvas['planSheer'], bx) * 500
        yc_mm = eval_hermite(curvas['planChine'], bx) * 500
        zs_mm = eval_hermite(curvas['profSheer'], bx) * 500
        zc_mm = eval_hermite(curvas['profChine'], bx) * 500
        zk_mm = eval_hermite(curvas['profKeel'], bx) * 500
        
        if yc_mm > 1:
            deg = np.degrees(np.arctan((zc_mm - zk_mm) / yc_mm))
            deg_str = f"{deg:.1f}°"
        else:
            deg_str = "-"

        row_y_sheer.append(f"{int(round(ys_mm))}")
        row_y_chine.append(f"{int(round(yc_mm))}")
        row_z_sheer.append(f"{int(round(zs_mm))}")
        row_z_chine.append(f"{int(round(zc_mm))}")
        row_z_keel.append(f"{int(round(zk_mm))}")
        row_v_angle.append(deg_str)

    table_data = [
        [Paragraph(f"<b>{h}</b>", table_header) for h in headers],
        [Paragraph(f"<b>{c}</b>" if idx==0 else c, table_cell) for idx, c in enumerate(row_y_sheer)],
        [Paragraph(f"<b>{c}</b>" if idx==0 else c, table_cell) for idx, c in enumerate(row_y_chine)],
        [Paragraph(f"<b>{c}</b>" if idx==0 else c, table_cell) for idx, c in enumerate(row_z_sheer)],
        [Paragraph(f"<b>{c}</b>" if idx==0 else c, table_cell) for idx, c in enumerate(row_z_chine)],
        [Paragraph(f"<b>{c}</b>" if idx==0 else c, table_cell) for idx, c in enumerate(row_z_keel)],
        [Paragraph(f"<b>{c}</b>" if idx==0 else c, table_cell) for idx, c in enumerate(row_v_angle)],
    ]

    col_w = [118] + [54]*11
    cotas_table = Table(table_data, colWidths=col_w)
    cotas_table.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), primary_color),
        ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#CBD5E0")),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.white, light_bg]),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING', (0,0), (-1,-1), 2),
        ('BOTTOMPADDING', (0,0), (-1,-1), 2),
        ('LEFTPADDING', (0,0), (-1,-1), 2),
        ('RIGHTPADDING', (0,0), (-1,-1), 2),
    ]))
    story.append(cotas_table)
    story.append(Spacer(1, 3))

    # Notas Técnicas
    story.append(Paragraph("• <b>Geometria Quinada:</b> Balizas poligonais formadas pelos vértices Quilha-Chine-Borda. Chine proporcionalizado a 80% da borda. | <b>$C_M$:</b> 0,75 fiel ao croqui. | <b>Alisamento:</b> 5 splines convexas validadas pelo padrão Brana.", body_style))

    doc.build(story, canvasmaker=NumberedCanvas)

if __name__ == "__main__":
    out_pdf = "/home/magdalena/eee/alunos/aristides-cheto/plano_de_linhas_2d_aristides_cheto.pdf"
    build_pdf(out_pdf)
    print(f"PDF successfully generated at: {out_pdf}")
