#!/usr/bin/env python3
"""
Envoie le digest du matin (DIGEST-DUJOUR-[date].md) vers le webhook n8n
qui déclenche l'email unique du jour (workflow VEILLE-DIGEST-EMAIL).

Lit N8N_HOST et FIDULIA_TOKEN depuis l'environnement si déjà exportés,
sinon charge directement ~/.config/fidulia/veille.env (plus besoin de
`source` en Bash avant l'appel).

Usage:
    python3 send_digest_webhook.py /chemin/vers/DIGEST-DUJOUR-2026-07-03.md

Remplace le heredoc python3 ad hoc de ROUTINE-VEILLE-MATIN.md §5.4, afin que
la permission Bash puisse être scopée à ce script exact plutôt qu'à python3
dans son ensemble.
"""
import argparse
import datetime
import html as html_module
import json
import os
import re
import sys
import urllib.request
import urllib.error

ENV_FILE = os.path.expanduser("~/.config/fidulia/veille.env")

CSS = """
<style>
  body,div{font-family:Arial,Helvetica,sans-serif;color:#0C132A}
  h1{font-size:22px;margin:0 0 4px}
  h2{font-size:17px;color:#D70459;margin:20px 0 6px}
  h3{font-size:15px;margin:14px 0 4px}
  p{margin:6px 0;line-height:1.55}
  table{border-collapse:collapse;width:100%;margin:10px 0}
  th{background:#0C132A;color:#fff;padding:7px 10px;text-align:left;font-size:13px}
  td{padding:6px 10px;border-bottom:1px solid #e8e8e8;font-size:13px}
  tr:nth-child(even) td{background:#f7f7f9}
  code{background:#f0f0f4;padding:1px 4px;border-radius:3px;font-size:12px}
  a{color:#D70459}
  hr{border:none;border-top:1px solid #e0e0e8;margin:18px 0}
  .footer{font-size:11px;color:#aaa;margin-top:24px}
</style>
"""


def load_env_file(path):
    """Parse un fichier shell simple (export KEY=VALUE) sans dépendre de `source`."""
    values = {}
    try:
        with open(path, "r", encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if not line or line.startswith("#"):
                    continue
                if line.startswith("export "):
                    line = line[len("export "):]
                if "=" not in line:
                    continue
                key, _, val = line.partition("=")
                values[key.strip()] = val.strip().strip('"').strip("'")
    except OSError:
        pass
    return values


def md_to_html(text: str) -> str:
    """
    Convertit le markdown du digest en HTML inline.
    Couvre : titres H1-H3, bold, italic, code, liens, tableaux, HR, listes, paragraphes.
    Sans dépendance externe.
    """
    lines = text.split("\n")
    out = []
    in_table = False
    in_list = False
    i = 0

    def inline(s: str) -> str:
        # Liens [texte](url)
        s = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', r'<a href="\2">\1</a>', s)
        # Bold **...**
        s = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', s)
        # Italic *...*
        s = re.sub(r'\*(.+?)\*', r'<em>\1</em>', s)
        # Code `...`
        s = re.sub(r'`([^`]+)`', r'<code>\1</code>', s)
        return s

    while i < len(lines):
        line = lines[i]

        # Ligne vide — ferme les blocs ouverts
        if line.strip() == "":
            if in_table:
                out.append("</table>")
                in_table = False
            if in_list:
                out.append("</ul>")
                in_list = False
            i += 1
            continue

        # HR ---
        if re.match(r'^-{3,}$', line.strip()):
            if in_table:
                out.append("</table>")
                in_table = False
            if in_list:
                out.append("</ul>")
                in_list = False
            out.append("<hr>")
            i += 1
            continue

        # Titres
        if line.startswith("### "):
            out.append(f"<h3>{inline(line[4:])}</h3>")
            i += 1
            continue
        if line.startswith("## "):
            out.append(f"<h2>{inline(line[3:])}</h2>")
            i += 1
            continue
        if line.startswith("# "):
            out.append(f"<h1>{inline(line[2:])}</h1>")
            i += 1
            continue

        # Tableau markdown (ligne qui commence par |)
        if line.startswith("|"):
            if not in_table:
                out.append('<table>')
                in_table = True
            cells = [c.strip() for c in line.split("|")[1:-1]]
            # Détecter si c'est le séparateur |---|---|
            if all(re.match(r'^[-:]+$', c) for c in cells if c):
                i += 1
                continue
            # Détecter si c'est la ligne d'en-tête (première ligne du tableau = toujours th)
            # On fait th si la ligne suivante est le séparateur
            next_line = lines[i + 1] if i + 1 < len(lines) else ""
            next_cells = [c.strip() for c in next_line.split("|")[1:-1]] if next_line.startswith("|") else []
            is_header = bool(next_cells) and all(re.match(r'^[-:]+$', c) for c in next_cells if c)
            tag = "th" if is_header else "td"
            row = "".join(f"<{tag}>{inline(c)}</{tag}>" for c in cells)
            out.append(f"<tr>{row}</tr>")
            i += 1
            continue

        # Ferme tableau si on sort des lignes |
        if in_table:
            out.append("</table>")
            in_table = False

        # Liste à puces - ou *
        if re.match(r'^[-*] ', line):
            if not in_list:
                out.append("<ul>")
                in_list = True
            out.append(f"<li>{inline(line[2:])}</li>")
            i += 1
            continue

        # Ferme liste si on sort
        if in_list:
            out.append("</ul>")
            in_list = False

        # Paragraphe normal
        out.append(f"<p>{inline(line)}</p>")
        i += 1

    # Fermeture des blocs ouverts
    if in_table:
        out.append("</table>")
    if in_list:
        out.append("</ul>")

    body = "\n".join(out)
    return (
        f'<div style="max-width:640px;margin:auto;">'
        f'{CSS}{body}'
        f'<p class="footer">Digest généré par la routine veille Fidulia · Claude Code</p>'
        f'</div>'
    )


def extract_subject(text: str) -> str:
    """Extrait le titre H1 du markdown comme sujet de l'email. Nettoie les emojis de début."""
    for line in text.split("\n"):
        if line.startswith("# "):
            title = line[2:].strip()
            # Retire les emojis Unicode et variation selectors en début de titre
            title = re.sub(r'^[\U0001F000-\U0001FFFF\U00002600-\U000027FF︀-️\s]+', '', title).strip()
            return title or line[2:].strip()
    return f"Digest Fidulia — {datetime.date.today().strftime('%d/%m/%Y')}"


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("digest_path", help="Chemin vers le fichier DIGEST-DUJOUR-[date].md")
    parser.add_argument("--endpoint", default="veille-digest-fidulia",
                         help="Nom du webhook n8n à appeler (défaut: veille-digest-fidulia)")
    args = parser.parse_args()

    host = os.environ.get("N8N_HOST")
    token = os.environ.get("FIDULIA_TOKEN")
    if not host or not token:
        file_values = load_env_file(ENV_FILE)
        host = host or file_values.get("N8N_HOST")
        token = token or file_values.get("FIDULIA_TOKEN")
    if not host or not token:
        print(f"N8N_HOST et FIDULIA_TOKEN introuvables (ni dans l'environnement, "
              f"ni dans {ENV_FILE}).", file=sys.stderr)
        sys.exit(1)

    try:
        with open(args.digest_path, "r", encoding="utf-8") as f:
            digest = f.read()
    except OSError as e:
        print(f"Impossible de lire {args.digest_path}: {e}", file=sys.stderr)
        sys.exit(1)

    subject = extract_subject(digest)
    html_body = md_to_html(digest)

    payload = json.dumps({
        "subject": subject,
        "html": html_body,
    }, ensure_ascii=False).encode("utf-8")

    req = urllib.request.Request(
        f"{host.rstrip('/')}/webhook/{args.endpoint}",
        data=payload,
        headers={"X-Fidulia-Token": token, "Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            print("Réponse n8n:", resp.read().decode("utf-8"))
    except urllib.error.URLError as e:
        print(f"Erreur POST {args.endpoint}: {e}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()
