#!/usr/bin/env python3
"""Costruisce il manuale: da `contenuti/*.md` a un solo file in `fatto/`.

Uso:    python build/costruisci.py    (su Windows può servire: py build/costruisci.py)
Serve:  Python 3.8 o più recente. Nessuna libreria da installare.

Il giro: prima chiama `controlla.py` (se trova un errore, qui non si arriva),
poi impagina i capitoli in `fatto/manuale.html`. Quel file si legge dal telefono
e, dall'anteprima di stampa del browser, esce in A4 con un capitolo per pagina:
è il tuo PDF. Il menu in alto sparisce in stampa.

Regola che vale più del codice: `fatto/` si rigenera, non si corregge.
Se l'uscita è sbagliata, l'errore sta in `contenuti/` o qui dentro.
"""

import html
import re
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
import controlla  # noqa: E402

RADICE = controlla.RADICE
USCITA = RADICE / "fatto" / "manuale.html"

# Cambia queste tre righe: sono l'intestazione del TUO manuale.
TITOLO = "Manuale del banco"
SOTTOTITOLO = "Ferramenta Esposito · Napoli — uso interno"
REVISIONE = "revisione di novembre 2026"


# ---------------------------------------------------------------- Markdown → HTML
# Sottoinsieme volutamente piccolo: titoli, paragrafi, elenchi, tabelle,
# citazioni, blocchi di codice, immagini, link, grassetto, corsivo, `codice`.
# Basta per un manuale. Se ti serve altro, aggiungilo qui: è una funzione sola.

def _inline(testo):
    testo = html.escape(testo, quote=False)
    testo = re.sub(r"`([^`]+)`", r"<code>\1</code>", testo)
    testo = re.sub(r"!\[([^\]]*)\]\(([^)\s]+)\)", r'<img src="\2" alt="\1">', testo)
    testo = re.sub(r"\[([^\]]+)\]\(([^)\s]+)\)", r'<a href="\2">\1</a>', testo)
    testo = re.sub(r"\*\*([^*]+)\*\*", r"<strong>\1</strong>", testo)
    testo = re.sub(r"(?<![\*\w])\*([^*]+)\*(?!\w)", r"<em>\1</em>", testo)
    return testo


def _ancora(testo):
    pulito = re.sub(r"[^a-z0-9]+", "-", testo.lower().replace("à", "a").replace("è", "e"))
    return pulito.strip("-") or "sezione"


def _riga_tabella(riga, cella="td"):
    celle = [c.strip() for c in riga.strip().strip("|").split("|")]
    return "<tr>" + "".join(f"<{cella}>{_inline(c)}</{cella}>" for c in celle) + "</tr>"


def a_html(corpo):
    righe = corpo.splitlines()
    pezzi, i = [], 0
    while i < len(righe):
        riga = righe[i]
        nudo = riga.strip()

        if not nudo:
            i += 1
            continue

        if nudo.startswith("```"):
            blocco, i = [], i + 1
            while i < len(righe) and not righe[i].strip().startswith("```"):
                blocco.append(html.escape(righe[i], quote=False))
                i += 1
            pezzi.append("<pre><code>" + "\n".join(blocco) + "</code></pre>")
            i += 1
            continue

        if nudo.startswith("#"):
            livello = len(nudo) - len(nudo.lstrip("#"))
            testo = nudo[livello:].strip()
            livello = min(livello, 6)  # il titolo del capitolo è già l'h1: nel testo parti da ##
            pezzi.append(f'<h{livello} id="{_ancora(testo)}">{_inline(testo)}</h{livello}>')
            i += 1
            continue

        if nudo.startswith(">"):
            blocco = []
            while i < len(righe) and righe[i].strip().startswith(">"):
                blocco.append(righe[i].strip().lstrip(">").strip())
                i += 1
            pezzi.append("<blockquote><p>" + _inline(" ".join(blocco)) + "</p></blockquote>")
            continue

        if nudo.startswith("|") and i + 1 < len(righe) and set(righe[i + 1].strip()) <= set("|-: "):
            testata = _riga_tabella(righe[i], "th")
            i += 2
            corpo_tabella = []
            while i < len(righe) and righe[i].strip().startswith("|"):
                corpo_tabella.append(_riga_tabella(righe[i]))
                i += 1
            pezzi.append(
                "<table><thead>" + testata + "</thead><tbody>"
                + "".join(corpo_tabella) + "</tbody></table>"
            )
            continue

        elenco_puntato = re.match(r"^[-*]\s+(.*)", nudo)
        elenco_numerato = re.match(r"^\d+[.)]\s+(.*)", nudo)
        if elenco_puntato or elenco_numerato:
            marcatore = "ul" if elenco_puntato else "ol"
            voci = []
            while i < len(righe):
                corrente = righe[i].strip()
                prossima = re.match(r"^[-*]\s+(.*)", corrente) if marcatore == "ul" \
                    else re.match(r"^\d+[.)]\s+(.*)", corrente)
                if not prossima:
                    break
                voci.append(f"<li>{_inline(prossima.group(1))}</li>")
                i += 1
            pezzi.append(f"<{marcatore}>" + "".join(voci) + f"</{marcatore}>")
            continue

        if set(nudo) <= set("-*_") and len(nudo) >= 3:
            pezzi.append("<hr>")
            i += 1
            continue

        paragrafo = []
        while i < len(righe) and righe[i].strip() and not re.match(r"^(#|>|\||```|[-*]\s|\d+[.)]\s)", righe[i].strip()):
            paragrafo.append(righe[i].strip())
            i += 1
        pezzi.append("<p>" + _inline(" ".join(paragrafo)) + "</p>")

    return "\n".join(pezzi)


# ---------------------------------------------------------------- impaginazione

FOGLIO_DI_STILE = """
:root { --testo: #1a1a1a; --tenue: #5a5a5a; --filo: #d8d8d8; }
* { box-sizing: border-box; }
body { margin: 0 auto; padding: 2rem 1.25rem 4rem; max-width: 38rem;
       font: 17px/1.6 Georgia, "Times New Roman", serif; color: var(--testo); }
nav.sommario { position: sticky; top: 0; background: #fff; padding: .75rem 0;
               border-bottom: 1px solid var(--filo); font-family: system-ui, sans-serif; font-size: 15px; }
nav.sommario a { display: block; padding: .15rem 0; color: var(--testo); }
h1 { font-size: 1.7rem; line-height: 1.25; margin: 2.5rem 0 .3rem; }
h2 { font-size: 1.25rem; margin: 2rem 0 .4rem; }
h3 { font-size: 1.05rem; margin: 1.5rem 0 .3rem; }
p, li { margin: .6rem 0; }
code { font: .88em/1.4 ui-monospace, "Courier New", monospace; background: #f2f2f2; padding: .1em .3em; }
pre { background: #f6f6f6; padding: .8rem; overflow-x: auto; border-left: 3px solid var(--filo); }
pre code { background: none; padding: 0; }
blockquote { margin: 1rem 0; padding-left: .9rem; border-left: 3px solid var(--filo); color: var(--tenue); }
table { border-collapse: collapse; width: 100%; font-size: .95em; }
th, td { border: 1px solid var(--filo); padding: .4rem .5rem; text-align: left; vertical-align: top; }
img { max-width: 100%; height: auto; }
.copertina { padding: 3rem 0 1rem; border-bottom: 2px solid var(--testo); }
.copertina .sottotitolo { color: var(--tenue); margin: .2rem 0; }
.capitolo { padding-top: 1rem; }
.stato { font-family: system-ui, sans-serif; font-size: 13px; color: var(--tenue);
         text-transform: uppercase; letter-spacing: .06em; }
footer { margin-top: 3rem; padding-top: .8rem; border-top: 1px solid var(--filo);
         font-family: system-ui, sans-serif; font-size: 13px; color: var(--tenue); }

@media print {
  @page { size: A4; margin: 22mm 20mm; }
  body { max-width: none; padding: 0; font-size: 11.5pt; }
  nav.sommario { display: none; }          /* niente roba da schermo sulla carta */
  .capitolo { break-before: page; page-break-before: always; }
  h1, h2, h3 { break-after: avoid-page; page-break-after: avoid; }
  pre, table, blockquote { break-inside: avoid; page-break-inside: avoid; }
  a { color: inherit; text-decoration: none; }
}
"""


def costruisci(capitoli):
    sommario = "\n".join(
        f'<a href="#cap-{c["numero"]}">{c["numero"]} · {html.escape(c["titolo"])}</a>'
        for c in capitoli
    )
    corpo = "\n".join(
        f'<section class="capitolo" id="cap-{c["numero"]}">\n'
        f'<h1>{html.escape(c["titolo"])}</h1>\n'
        f'<p class="stato">{c["numero"]} · {c["stato"]}</p>\n'
        f'{a_html(c["corpo"])}\n</section>'
        for c in capitoli
    )
    parole = sum(c["parole"] for c in capitoli)
    pagina = f"""<!doctype html>
<html lang="it">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{html.escape(TITOLO)}</title>
<style>{FOGLIO_DI_STILE}</style>
<nav class="sommario">{sommario}</nav>
<header class="copertina">
  <h1>{html.escape(TITOLO)}</h1>
  <p class="sottotitolo">{html.escape(SOTTOTITOLO)}</p>
  <p class="sottotitolo">{html.escape(REVISIONE)} · {len(capitoli)} capitoli · {parole} parole</p>
</header>
{corpo}
<footer>Generato da build/costruisci.py. Non si corregge a mano: si corregge la fonte in contenuti/ e si rigenera.</footer>
</html>
"""
    USCITA.parent.mkdir(parents=True, exist_ok=True)
    USCITA.write_text(pagina, encoding="utf-8")
    return parole


if __name__ == "__main__":
    capitoli, errori, avvisi = controlla.controlla()
    controlla.stampa_esito(capitoli, errori, avvisi)
    if errori:
        print("\nBuild non eseguito: il cancello è chiuso.")
        sys.exit(1)

    parole = costruisci(capitoli)
    print("\nCOSTRUZIONE")
    print(f"  Scritto: fatto/manuale.html ({len(capitoli)} capitoli, {parole} parole)")
    print("\nIl giro per la prossima modifica:")
    print("  1. apri il capitolo giusto in contenuti/ e cambia lì;")
    print("  2. lancia python build/costruisci.py;")
    print("  3. apri fatto/manuale.html nel browser; per il PDF: Stampa, poi Salva come PDF (A4).")
