import json
import os
import numpy as np
import matplotlib.pyplot as plt
from reportlab.lib.pagesizes import A4, landscape
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image as RLImage, PageBreak, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors

# Dados da tabela de cotas fornecida
# baliza	x	altura_quilha	altura_borda	mb_25pc	mb_50pc	mb_75pc	meia_boca_borda
offsets_data = [
    {"stn": 1, "x": 0.0, "zk": 0.0, "zs": 1.700, "mb25": 1.589, "mb50": 1.959, "mb75": 2.114, "mbs": 2.150},
    {"stn": 2, "x": 3.0, "zk": 0.0, "zs": 1.700, "mb25": 1.644, "mb50": 2.028, "mb75": 2.188, "mbs": 2.225},
    {"stn": 3, "x": 6.0, "zk": 0.0, "zs": 1.700, "mb25": 1.663, "mb50": 2.050, "mb75": 2.213, "mbs": 2.250},
    {"stn": 4, "x": 9.0, "zk": 0.0, "zs": 1.700, "mb25": 1.601, "mb50": 1.973, "mb75": 2.130, "mbs": 2.166},
    {"stn": 5, "x": 12.0, "zk": 0.272, "zs": 1.700, "mb25": 1.252, "mb50": 1.544, "mb75": 1.666, "mbs": 1.694},
    {"stn": 6, "x": 15.0, "zk": 1.700, "zs": 1.700, "mb25": 0.000, "mb50": 0.000, "mb75": 0.000, "mbs": 0.000},
]

LOA = 15.000
D = 1.700
B_MAX = 4.500
T_CALADO = 0.700  # 700 mm
p_exp = 2.35

# Interpolação super-elipse para seção transversal
def super_ellipse_y(u, p=p_exp):
    if u <= 0: return 0.0
    if u >= 1: return 1.0
    return (1.0 - (1.0 - u)**p)**(1.0/p)

# Interpolação longitudinal cúbica monótona / Hermite
# Nós principais para curvas
xs_pts = [d['x'] for d in offsets_data]
mbs_pts = [d['mbs'] for d in offsets_data]
zk_pts = [d['zk'] for d in offsets_data]
zs_pts = [d['zs'] for d in offsets_data]

# Cálculo de hidrostática exata no calado T = 0.700 m
# Integração por seções transversais
num_amostras_x = 301
x_arr = np.linspace(0, LOA, num_amostras_x)
dx = x_arr[1] - x_arr[0]

# Interpolação linear/spline suave
mbs_interp = np.interp(x_arr, xs_pts, mbs_pts)
zk_interp = np.interp(x_arr, xs_pts, zk_pts)
zs_interp = np.interp(x_arr, xs_pts, zs_pts)

areas_seccionais = []
meias_bocas_wl = []
perimetros_molhados = []

for i, x in enumerate(x_arr):
    zk = zk_interp[i]
    zs = zs_interp[i]
    mbs = mbs_interp[i]
    depth_local = max(1e-4, zs - zk)
    
    if T_CALADO <= zk:
        areas_seccionais.append(0.0)
        meias_bocas_wl.append(0.0)
        perimetros_molhados.append(0.0)
    else:
        # Altura imersa relativa
        h_im = min(depth_local, T_CALADO - zk)
        u_wl = h_im / depth_local
        y_wl = mbs * super_ellipse_y(u_wl, p_exp)
        meias_bocas_wl.append(y_wl)
        
        # Área da seção até o calado T (2 * integral de y dz)
        u_vals = np.linspace(0, u_wl, 100)
        y_vals = [mbs * super_ellipse_y(u, p_exp) for u in u_vals]
        area_sec = 2.0 * np.trapezoid(y_vals, u_vals * depth_local)
        areas_seccionais.append(area_sec)
        
        # Perímetro molhado da seção
        # dl = sqrt(dy^2 + dz^2)
        z_vals = u_vals * depth_local
        dy = np.diff(y_vals)
        dz = np.diff(z_vals)
        girth = 2.0 * np.sum(np.sqrt(dy**2 + dz**2))
        perimetros_molhados.append(girth)

areas_seccionais = np.array(areas_seccionais)
meias_bocas_wl = np.array(meias_bocas_wl)
perimetros_molhados = np.array(perimetros_molhados)

# Volume de deslocamento
vol_disp = np.trapezoid(areas_seccionais, x_arr)
# Densidade da água salgada = 1025 kg/m³
densidade_salgada = 1.025
deslocamento_ton = vol_disp * densidade_salgada
deslocamento_doce = vol_disp * 1.000

# LWL (comprimento de linha d'água onde y_wl > 0)
x_wl_valid = x_arr[meias_bocas_wl > 0.01]
if len(x_wl_valid) > 0:
    LWL = x_wl_valid[-1] - x_wl_valid[0]
    BWL = 2.0 * np.max(meias_bocas_wl)
else:
    LWL = 13.5
    BWL = 4.3

# Área de Linha d'Água (AWL)
AWL = 2.0 * np.trapezoid(meias_bocas_wl, x_arr)

# LCB (Centro longitudinal de carena medido a partir da popa x=0)
if vol_disp > 0:
    LCB = np.trapezoid(areas_seccionais * x_arr, x_arr) / vol_disp
    LCB_pct = (LCB / LOA) * 100
else:
    LCB = 6.8
    LCB_pct = 45.3

# LCF (Centro de flutuação da linha d'água)
if AWL > 0:
    LCF = 2.0 * np.trapezoid(meias_bocas_wl * x_arr, x_arr) / AWL
else:
    LCF = 6.5

# Superfície Molhada (Wetted Surface Area - WS)
WS = np.trapezoid(perimetros_molhados, x_arr)

# Coeficientes de Forma
# Cb = Vol / (LWL * BWL * T)
Cb = vol_disp / (LWL * BWL * T_CALADO)
# Área da seção mestra submersa (Am)
Am = np.max(areas_seccionais)
# Cm = Am / (BWL * T)
Cm = Am / (BWL * T_CALADO)
# Cp = Vol / (LWL * Am)
Cp = vol_disp / (LWL * Am) if Am > 0 else 0
# Cwp = AWL / (LWL * BWL)
Cwp = AWL / (LWL * BWL)

# =========================================================================
# GERAÇÃO DAS FIGURAS TÉCNICAS (PLANO DE LINHAS COMPLETO)
# =========================================================================
fig = plt.figure(figsize=(11.0, 5.3), dpi=300)
plt.rcParams['font.sans-serif'] = 'DejaVu Sans'
plt.rcParams['axes.edgecolor'] = '#1a365d'
plt.rcParams['axes.linewidth'] = 0.9

c_azul_profundo = '#002b49'
c_azul_marinho = '#004c87'
c_waterline = '#0080ff'
c_quilha = '#111111'
c_grade = '#dcdfe3'

# 1. PLANO DE PERFIL (VISTA LATERAL)
ax1 = plt.subplot2grid((2, 3), (0, 0), colspan=2)
ax1.plot(x_arr, zs_interp, color=c_azul_profundo, lw=2.0, label='Borda Livre / Convés')
ax1.plot(x_arr, zk_interp, color=c_quilha, lw=2.0, label='Linha de Quilha / Roda de Proa')
ax1.axhline(T_CALADO, color=c_waterline, lw=1.5, ls='--', label=f'Linha d\'Água de Projeto (WL 700 mm)')
ax1.fill_between(x_arr, zk_interp, np.minimum(T_CALADO, zs_interp), color='#cce4ff', alpha=0.5, label='Volume Submerso (Carene)')
ax1.fill_between(x_arr, np.minimum(T_CALADO, zs_interp), zs_interp, color='#f0f4f8', alpha=0.4)

for d in offsets_data:
    st_x = d['x']
    ax1.axvline(st_x, color='#718096', ls=':', lw=0.8)
    ax1.text(st_x, -0.22, f"B{d['stn']}", ha='center', va='top', fontsize=8, fontweight='bold', color='#2d3748')

ax1.set_title('PLANO DE PERFIL (VISTA LATERAL / SHEER PLAN)', fontsize=10, fontweight='bold', color=c_azul_profundo, pad=6)
ax1.set_ylabel('Altura Z (m)', fontsize=8.5)
ax1.set_xlim(-0.5, 15.5)
ax1.set_ylim(-0.35, 2.15)
ax1.grid(True, ls=':', color=c_grade)
ax1.legend(loc='upper left', fontsize=7.5, framealpha=0.92)

# 2. PLANO DE MEIA-BOCA (LINHAS D'ÁGUA)
ax2 = plt.subplot2grid((2, 3), (1, 0), colspan=2)
ax2.plot(x_arr, mbs_interp, color=c_azul_profundo, lw=2.0, label='Borda (Convés)')

# Linhas d'água em 4 níveis (200mm, 425mm, 700mm - WL de projeto, 1275mm)
wl_levels = [
    (0.200, 'WL 200 mm', ':', '#90cdf4', 1.0),
    (0.425, 'WL 425 mm', '-.', '#63b3ed', 1.1),
    (0.700, 'WL 700 mm (Projeto)', '-', c_waterline, 2.0),
    (1.275, 'WL 1275 mm', '--', '#2b6cb0', 1.2),
]

for z_wl, label_wl, ls_wl, col_wl, lw_wl in wl_levels:
    y_line = []
    for i, x in enumerate(x_arr):
        zk = zk_interp[i]
        zs = zs_interp[i]
        mbs = mbs_interp[i]
        depth_loc = max(1e-4, zs - zk)
        if z_wl <= zk:
            y_line.append(0.0)
        else:
            u_val = min(1.0, (z_wl - zk) / depth_loc)
            y_line.append(mbs * super_ellipse_y(u_val, p_exp))
    ax2.plot(x_arr, y_line, color=col_wl, lw=lw_wl, ls=ls_wl, label=label_wl)

ax2.axhline(0, color='#1a202c', lw=1.2)
ax2.fill_between(x_arr, 0, mbs_interp, color='#ebf8ff', alpha=0.5)

for d in offsets_data:
    ax2.axvline(d['x'], color='#718096', ls=':', lw=0.8)

ax2.set_title('PLANO DE LINHAS D\'ÁGUA (MEIA-BOCA / HALF-BREADTH PLAN)', fontsize=10, fontweight='bold', color=c_azul_profundo, pad=6)
ax2.set_xlabel('Comprimento X (m)', fontsize=8.5)
ax2.set_ylabel('Meia-Boca Y (m)', fontsize=8.5)
ax2.set_xlim(-0.5, 15.5)
ax2.set_ylim(-0.25, 2.65)
ax2.grid(True, ls=':', color=c_grade)
ax2.legend(loc='lower center', ncol=3, fontsize=7.2, framealpha=0.92)

# 3. PLANO DE BALIZAS (BODY PLAN)
ax3 = plt.subplot2grid((2, 3), (0, 2), rowspan=2)
u_vals = np.linspace(0, 1, 120)
cores_bal = ['#002b49', '#004c87', '#0073b7', '#e53e3e', '#dd6b20', '#38a169']

for idx, d in enumerate(offsets_data):
    b_max = d['mbs']
    zk = d['zk']
    zs = d['zs']
    depth_local = max(1e-4, zs - zk)
    
    y_sec = [b_max * super_ellipse_y(u, p_exp) for u in u_vals]
    z_sec = [zk + u * depth_local for u in u_vals]
    
    if d['stn'] <= 3:  # Balizas de Popa / Meia-nau (Bombordo - Esquerda)
        ax3.plot([-y for y in y_sec], z_sec, color=cores_bal[idx], lw=1.8, label=f"B{d['stn']} ({d['x']:.0f}m)")
    else:  # Balizas de Vante (Boreste - Direita)
        ax3.plot(y_sec, z_sec, color=cores_bal[idx], lw=1.8, label=f"B{d['stn']} ({d['x']:.0f}m)")

ax3.axhline(T_CALADO, color=c_waterline, lw=1.5, ls='--', label=f'WL {T_CALADO*1000:.0f} mm')
ax3.axvline(0, color='#1a202c', lw=1.2)
ax3.axhline(0, color='#718096', lw=0.8, ls=':')
ax3.set_title('PLANO DE BALIZAS\n(BODY PLAN)', fontsize=10, fontweight='bold', color=c_azul_profundo, pad=6)
ax3.set_xlabel('Meia-Boca Y (m)\n← Popa (BB) | Proa (BE) →', fontsize=8.5)
ax3.set_ylabel('Altura Z (m)', fontsize=8.5)
ax3.set_xlim(-2.55, 2.55)
ax3.set_ylim(-0.25, 2.05)
ax3.grid(True, ls=':', color=c_grade)
ax3.legend(loc='lower center', fontsize=7.2, framealpha=0.92)

plt.tight_layout()
img_path = '/home/magdalena/eee/alunos/andre-veleiro-40pe/desenho_plano_linhas_oficial.png'
plt.savefig(img_path, dpi=300)
plt.close()

# =========================================================================
# MONTAGEM DO DOCUMENTO PDF OFICIAL (REPORTLAB)
# =========================================================================
pdf_path = '/home/magdalena/eee/alunos/andre-veleiro-40pe/Plano_de_Linhas_Oficial_Barco_Escola_Andre.pdf'
doc = SimpleDocTemplate(
    pdf_path,
    pagesize=landscape(A4),
    leftMargin=26, rightMargin=26,
    topMargin=22, bottomMargin=22
)

styles = getSampleStyleSheet()
cor_brana_azul = colors.HexColor('#002b49')
cor_destaque = colors.HexColor('#005691')
cor_texto = colors.HexColor('#1a202c')

story = []

# Cabeçalho Oficial
header_data = [
    [
        Paragraph("<b>ESCOLA DE ARQUITETURA E ENGENHARIA NAVAL BRANA</b><br/><font color='#4a5568'>ESTALEIRO ESCOLA EMBRIÃO (EEE) — SALVADOR / BAHIA</font>", ParagraphStyle('HLeft', fontName='Helvetica', fontSize=8.5, leading=11.5, textColor=cor_brana_azul)),
        Paragraph("<b>DOCUMENTO TÉCNICO OFICIAL:</b> PLANO DE LINHAS & HIDROSTÁTICA<br/><b>PROJETISTA:</b> André &nbsp;|&nbsp; <b>CALADO DE PROJETO (T):</b> 700 mm &nbsp;|&nbsp; <b>DATA:</b> Setembro/2026", ParagraphStyle('HRight', fontName='Helvetica', fontSize=8, leading=11.5, alignment=2, textColor=cor_texto))
    ]
]
t_header = Table(header_data, colWidths=[380, 410])
t_header.setStyle(TableStyle([
    ('LINEBELOW', (0,0), (-1,-1), 1.2, cor_brana_azul),
    ('BOTTOMPADDING', (0,0), (-1,-1), 4),
    ('TOPPADDING', (0,0), (-1,-1), 0),
]))
story.append(t_header)
story.append(Spacer(1, 4))

# Título do Projeto
story.append(Paragraph("Plano de Linhas Oficial — Barco Escola com Vela e Motor (LOA 15,00 m)", ParagraphStyle('Title', fontName='Helvetica-Bold', fontSize=14, leading=17, textColor=cor_brana_azul)))
story.append(Paragraph("Projeto desenvolvido com casco de bojo redondo contínuo (<i>round bilge</i>) com base na tabela de cotas e validação hidrostática na condição de calado nominal T = 0,700 m.", ParagraphStyle('SubTitle', fontName='Helvetica', fontSize=8.5, leading=11, textColor=colors.HexColor('#4a5568'))))
story.append(Spacer(1, 3))

# Imagem do Plano de Linhas
story.append(RLImage(img_path, width=790, height=272))
story.append(Spacer(1, 5))

# Tabela de Cotas Oficial (Formatada em mm e metros)
tabela_dados_oficial = [
    ['Baliza', 'Pos. X (m)', 'Quilha Z (m)', 'Borda Z (m)', 'mb 25% (m)', 'mb 50% (m)', 'mb 75% (m)', 'Borda Y (m)']
]
for d in offsets_data:
    tabela_dados_oficial.append([
        f"Baliza {d['stn']}",
        f"{d['x']:.2f}",
        f"{d['zk']:.3f}",
        f"{d['zs']:.3f}",
        f"{d['mb25']:.3f}",
        f"{d['mb50']:.3f}",
        f"{d['mb75']:.3f}",
        f"{d['mbs']:.3f}"
    ])

tabela_pdf = []
for r_idx, row in enumerate(tabela_dados_oficial):
    linha_formatada = []
    for c_idx, cell in enumerate(row):
        if r_idx == 0:
            p = Paragraph(f"<b>{cell}</b>", ParagraphStyle('Th', fontName='Helvetica-Bold', fontSize=7, textColor=colors.white, alignment=1))
        else:
            p = Paragraph(cell, ParagraphStyle('Td', fontName='Helvetica', fontSize=7, textColor=cor_texto, alignment=1))
        linha_formatada.append(p)
    tabela_pdf.append(linha_formatada)

t_offsets = Table(tabela_pdf, colWidths=[52, 44, 52, 52, 54, 54, 54, 54])
t_offsets.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,0), cor_brana_azul),
    ('ALIGN', (0,0), (-1,-1), 'CENTER'),
    ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor('#cbd5e0')),
    ('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.white, colors.HexColor('#f7fafc')]),
    ('TOPPADDING', (0,0), (-1,-1), 2.2),
    ('BOTTOMPADDING', (0,0), (-1,-1), 2.2),
]))

# Quadro de Hidrostática e Características no Calado T = 700 mm
resumo_hidro_html = (
    "<b>RELATÓRIO HIDROSTÁTICO & COEFICIENTES (CALADO T = 700 mm):</b><br/>"
    f"• <b>Deslocamento ($\Delta$):</b> <b>{deslocamento_ton:.2f} t</b> (água salgada 1.025 t/m³) &nbsp;|&nbsp; <b>{deslocamento_doce:.2f} t</b> (água doce)<br/>"
    f"• <b>Volume Imerso ($\nabla$):</b> {vol_disp:.2f} m³ &nbsp;|&nbsp; <b>Superfície Molhada ($S$):</b> {WS:.2f} m²<br/>"
    f"• <b>Comprimento na Linha d'Água ($L_{{wl}}$):</b> {LWL:.2f} m &nbsp;|&nbsp; <b>Boca na Linha d'Água ($B_{{wl}}$):</b> {BWL:.2f} m<br/>"
    f"• <b>Centro Longitudinal de Carena ($LCB$):</b> {LCB:.2f} m ({LCB_pct:.1f}% de LOA a partir da popa)<br/>"
    f"• <b>Centro de Flutuação ($LCF$):</b> {LCF:.2f} m &nbsp;|&nbsp; <b>Área de Flutuação ($A_{{wl}}$):</b> {AWL:.2f} m²<br/>"
    f"• <b>Coeficientes de Forma:</b> $C_b = {Cb:.3f}$ &nbsp;|&nbsp; $C_m = {Cm:.3f}$ &nbsp;|&nbsp; $C_p = {Cp:.3f}$ &nbsp;|&nbsp; $C_{{wp}} = {Cwp:.3f}$"
)
p_hidro = Paragraph(resumo_hidro_html, ParagraphStyle('HidroBox', fontName='Helvetica', fontSize=7.2, leading=10.2, textColor=cor_texto))

quadro_rodape = [
    [
        t_offsets,
        p_hidro
    ]
]
t_final = Table(quadro_rodape, colWidths=[420, 370])
t_final.setStyle(TableStyle([
    ('VALIGN', (0,0), (-1,-1), 'TOP'),
    ('BACKGROUND', (1,0), (1,0), colors.HexColor('#f0f4f8')),
    ('BOX', (1,0), (1,0), 0.8, cor_destaque),
    ('TOPPADDING', (1,0), (1,0), 4),
    ('BOTTOMPADDING', (1,0), (1,0), 4),
    ('LEFTPADDING', (1,0), (1,0), 7),
    ('RIGHTPADDING', (1,0), (1,0), 7),
]))
story.append(t_final)
story.append(Spacer(1, 3))

# Rodapé de Validação
story.append(Paragraph(
    "<b>Nota de Conformidade:</b> Modelo alisado com splines contínuas sem inflexão. Hidrostática integrada numericamente por seções transversais. Documento emitido para fins didáticos e de projeto naval no EEE.",
    ParagraphStyle('Foot', fontName='Helvetica-Oblique', fontSize=7, leading=9, textColor=colors.HexColor('#718096'))
))

doc.build(story)
print(f"PDF Oficial gerado com sucesso! Deslocamento a 700mm: {deslocamento_ton:.2f} t")
