"""
Router FastAPI — Génération PDF étiquettes béton
Format : A4 Paysage (297×210mm)
Grille  : 5 colonnes × 2 lignes
Étiquette : 56mm large × 105mm haute
Pas de rotation — texte lisible directement

Structure de haut en bas :
  Logo          : 10mm (pleine largeur)
  ┌─────────────────────────────────┐
  │ Bande (7mm) │ Stats   10mm      │
  │   couleur   │ Client  10mm      │
  │   vertical  │ Projet  10mm      │
  │             │ Pièce   33mm      │
  └─────────────────────────────────┘
  Zone béton    : 25mm (pleine largeur)
"""
import io
import base64
from typing import List, Optional
from fastapi import APIRouter, HTTPException
from fastapi.responses import StreamingResponse
from pydantic import BaseModel

from reportlab.pdfgen import canvas
from reportlab.lib.units import mm
from reportlab.lib.colors import HexColor, black, white
from reportlab.lib.utils import ImageReader

router = APIRouter(prefix="/api/etiquettes", tags=["etiquettes"])

# ── PAGE PAYSAGE ──────────────────────────────────────────────────────────────
PAGE_W = 297 * mm
PAGE_H = 210 * mm

# ── GRILLE : 5 colonnes × 2 lignes ───────────────────────────────────────────
ETIQ_W = 56    # mm — largeur étiquette
ETIQ_H = 105   # mm — hauteur étiquette

COLS = 5
ROWS = 2

# Centres des colonnes
COL_CENTERS_MM = [ETIQ_W * (i + 0.5) for i in range(COLS)]
# [28, 84, 140, 196, 252]

# Centres des lignes
ROW_CENTERS_MM = [ETIQ_H * (i + 0.5) for i in range(ROWS)]
# [52.5, 157.5]

# ── ZONES (mm, de haut en bas) ────────────────────────────────────────────────
LOGO_H   = 10
BANDE_W  =  7   # largeur de la bande couleur (sur axe X)
STATS_H  = 10
CLIENT_H = 10
PROJET_H = 10
BETON_H  = 25
PIECE_H  = ETIQ_H - LOGO_H - STATS_H - CLIENT_H - PROJET_H - BETON_H
# = 105 - 10 - 10 - 10 - 10 - 25 = 40mm


# ── SCHÉMA PYDANTIC ───────────────────────────────────────────────────────────
class EtiquettePiece(BaseModel):
    reference: str
    client_nom: Optional[str] = ""
    projet_nom: str
    projet_couleur: Optional[str] = "#4facfe"
    niveau: Optional[str] = ""
    litres: int
    poids_t: float
    logo_b64: Optional[str] = None


class EtiquettesRequest(BaseModel):
    pieces: List[EtiquettePiece]
    draw_grid: bool = False


# ── HELPERS ───────────────────────────────────────────────────────────────────
def pt(x_mm: float) -> float:
    return x_mm * mm


def hex_color(h: str) -> HexColor:
    h = h.strip()
    if not h.startswith("#"):
        h = "#" + h
    try:
        return HexColor(h)
    except Exception:
        return HexColor("#4facfe")


def truncate(c, text, font, size, max_pt):
    while len(text) > 1 and c.stringWidth(text, font, size) > max_pt:
        text = text[:-1]
    return text


def draw_label(c: canvas.Canvas, cx_mm: float, cy_mm: float,
               piece: EtiquettePiece, logo_reader=None):
    """
    Dessine une étiquette dont le centre est (cx_mm, cy_mm).
    Pas de rotation — contenu lisible directement.
    Origine ReportLab = bas-gauche de la page.
    """
    col = hex_color(piece.projet_couleur or "#4facfe")

    # Coin bas-gauche de l'étiquette
    x0 = pt(cx_mm - ETIQ_W / 2)
    y0 = PAGE_H - pt(cy_mm + ETIQ_H / 2)

    W = pt(ETIQ_W)
    H = pt(ETIQ_H)

    # ── FOND BLANC ────────────────────────────────────────────────────────────
    c.setFillColor(white)
    c.rect(x0, y0, W, H, stroke=0, fill=1)

    # Curseur Y (on part du haut et on descend)
    # En ReportLab Y croît vers le haut, donc "descendre" = soustraire
    cur_y = y0 + H  # haut de l'étiquette

    # ── 1. LOGO (10mm hauteur, pleine largeur) ────────────────────────────────
    lh = pt(LOGO_H)
    cur_y -= lh
    c.setStrokeColor(HexColor("#eeeeee"))
    c.setLineWidth(0.3)
    c.line(x0, cur_y, x0 + W, cur_y)
    if logo_reader:
        iw = pt(ETIQ_W - 4)
        ih = pt(LOGO_H - 2)
        c.drawImage(logo_reader,
                    x0 + (W - iw) / 2,
                    cur_y + (lh - ih) / 2,
                    iw, ih,
                    preserveAspectRatio=True, mask='auto')
    else:
        c.setFillColor(black)
        c.setFont("Helvetica-Bold", 6)
        c.drawCentredString(x0 + W/2, cur_y + lh/2 - 2, "BÉTON SOLUTIONS")

    # ── 2. ZONE CENTRALE (bande + stats + client + projet + pièce) ────────────
    zone_centrale_h = pt(STATS_H + CLIENT_H + PROJET_H + PIECE_H)

    # ── 2a. BANDE COULEUR (7mm large, hauteur = zone centrale) ────────────────
    bw = pt(BANDE_W)
    c.setFillColor(col)
    c.rect(x0, cur_y - zone_centrale_h, bw, zone_centrale_h, stroke=0, fill=1)

    # Niveau en vertical dans la bande
    if piece.niveau:
        c.saveState()
        c.translate(x0 + bw/2, cur_y - zone_centrale_h/2)
        c.rotate(90)
        c.setFillColor(white)
        c.setFont("Helvetica-Bold", 6)
        c.drawCentredString(0, -2, piece.niveau.upper())
        c.restoreState()

    # X de départ des zones droites (après bande)
    xr = x0 + bw
    wr = W - bw  # largeur disponible à droite de la bande

    # ── 2b. STATS poids + béton (10mm) ────────────────────────────────────────
    sh = pt(STATS_H)
    cur_y -= sh
    c.setStrokeColor(HexColor("#eeeeee"))
    c.line(xr, cur_y, x0 + W, cur_y)

    pad = pt(1)
    sw = (wr - 3*pad) / 2

    # Stat poids
    c.setFillColor(HexColor("#f5f5f5"))
    c.roundRect(xr + pad, cur_y + pad, sw, sh - 2*pad, pt(1), stroke=0, fill=1)
    c.setFillColor(HexColor("#999999"))
    c.setFont("Helvetica-Bold", 4)
    c.drawCentredString(xr + pad + sw/2, cur_y + sh - pt(3), "POIDS")
    c.setFillColor(black)
    c.setFont("Helvetica-Bold", 6)
    c.drawCentredString(xr + pad + sw/2, cur_y + pt(1.5), f"{piece.poids_t:.3f} T")

    # Stat béton
    sx2 = xr + 2*pad + sw
    c.setFillColor(HexColor("#f5f5f5"))
    c.roundRect(sx2, cur_y + pad, sw, sh - 2*pad, pt(1), stroke=0, fill=1)
    c.setFillColor(HexColor("#999999"))
    c.setFont("Helvetica-Bold", 4)
    c.drawCentredString(sx2 + sw/2, cur_y + sh - pt(3), "BÉTON")
    c.setFillColor(black)
    c.setFont("Helvetica-Bold", 6)
    c.drawCentredString(sx2 + sw/2, cur_y + pt(1.5), f"{piece.litres} L")

    # ── 2c. CLIENT (10mm) ─────────────────────────────────────────────────────
    clh = pt(CLIENT_H)
    cur_y -= clh
    c.setStrokeColor(HexColor("#eeeeee"))
    c.line(xr, cur_y, x0 + W, cur_y)
    txt = (piece.client_nom or "").upper()
    txt = truncate(c, txt, "Helvetica-Bold", 5.5, wr - pt(2))
    c.setFillColor(HexColor("#555555"))
    c.setFont("Helvetica-Bold", 5.5)
    c.drawCentredString(xr + wr/2, cur_y + clh/2 - 2, txt)

    # ── 2d. PROJET (10mm) ─────────────────────────────────────────────────────
    prh = pt(PROJET_H)
    cur_y -= prh
    c.setStrokeColor(HexColor("#eeeeee"))
    c.line(xr, cur_y, x0 + W, cur_y)
    txt_proj = (piece.projet_nom or "").upper()
    txt_proj = truncate(c, txt_proj, "Helvetica-Bold", 6, wr - pt(2))
    c.setFillColor(black)
    c.setFont("Helvetica-Bold", 6)
    c.drawCentredString(xr + wr/2, cur_y + prh/2 - 2, txt_proj)

    # ── 2e. PIÈCE référence (40mm) ────────────────────────────────────────────
    pih = pt(PIECE_H)
    cur_y -= pih
    c.setStrokeColor(HexColor("#eeeeee"))
    c.line(xr, cur_y, x0 + W, cur_y)
    ref = piece.reference
    ref_size = 28 if len(ref) <= 4 else (22 if len(ref) <= 6 else 16)
    c.setFillColor(black)
    c.setFont("Helvetica-Bold", ref_size)
    c.drawCentredString(xr + wr/2, cur_y + pih/2 - ref_size*0.35, ref)

    # ── 3. ZONE BÉTON (25mm, pleine largeur) ──────────────────────────────────
    bth = pt(BETON_H)
    margin = pt(2)
    c.setStrokeColor(HexColor("#cccccc"))
    c.setDash(2, 2)
    c.setLineWidth(0.5)
    c.rect(x0 + margin, y0 + margin, W - 2*margin, bth - 2*margin,
           stroke=1, fill=0)
    c.setDash()
    c.setFillColor(HexColor("#bbbbbb"))
    c.setFont("Helvetica", 4.5)
    c.drawCentredString(x0 + W/2, y0 + bth/2 - 2,
                        "↓  À PLANTER DANS LE BÉTON  ↓")


# ── ROUTE PDF ─────────────────────────────────────────────────────────────────
@router.post("/pdf")
async def generer_pdf_etiquettes(req: EtiquettesRequest):
    if not req.pieces:
        raise HTTPException(status_code=400, detail="Aucune pièce fournie")

    buf = io.BytesIO()
    c = canvas.Canvas(buf, pagesize=(PAGE_W, PAGE_H))

    logo_reader = None
    if req.pieces[0].logo_b64:
        try:
            logo_bytes = base64.b64decode(req.pieces[0].logo_b64)
            logo_reader = ImageReader(io.BytesIO(logo_bytes))
        except Exception:
            pass

    pieces_par_page = COLS * ROWS  # 10
    total = len(req.pieces)

    for page_idx in range(0, total, pieces_par_page):
        page_pieces = req.pieces[page_idx:page_idx + pieces_par_page]

        if req.draw_grid:
            c.setStrokeColor(HexColor("#cccccc"))
            c.setLineWidth(0.3)
            for i in range(COLS + 1):
                c.line(pt(i * ETIQ_W), 0, pt(i * ETIQ_W), PAGE_H)
            for i in range(ROWS + 1):
                c.line(0, PAGE_H - pt(i * ETIQ_H),
                       PAGE_W, PAGE_H - pt(i * ETIQ_H))

        for i, piece in enumerate(page_pieces):
            col_idx = i % COLS
            row_idx = i // COLS
            draw_label(c,
                       COL_CENTERS_MM[col_idx],
                       ROW_CENTERS_MM[row_idx],
                       piece, logo_reader)

        if page_idx + pieces_par_page < total:
            c.showPage()

    c.save()
    buf.seek(0)

    return StreamingResponse(
        buf,
        media_type="application/pdf",
        headers={"Content-Disposition": "inline; filename=etiquettes.pdf"}
    )
