#!/usr/bin/env python3
"""
Import des saints et dictons dans la base de données de la webapp Jardin.

Les données sont INDÉPENDANTES DE L'ANNÉE : stockées par (mois, jour) uniquement.

Sources JSON :
  - saints_du_jour.json    → table saint_du_jour
  - dictons_du_jour.json   → table dicton

Usage :
  # Import complet (remplace les données existantes)
  python import_webapp_db.py

  # Import vers une autre DB
  python import_webapp_db.py --db /chemin/vers/jardin.db

  # Mode append (ajoute sans supprimer les existants)
  python import_webapp_db.py --mode append

  # Seulement les saints ou seulement les dictons
  python import_webapp_db.py --only saints
  python import_webapp_db.py --only dictons

  # Tagger les dictons avec une région
  python import_webapp_db.py --region "Auvergne"

  # Prévisualisation sans modification
  python import_webapp_db.py --dry-run
"""
import argparse
import json
import sqlite3
import sys
from datetime import datetime, timezone
from pathlib import Path

# Chemins par défaut relatifs à ce script
_HERE = Path(__file__).parent
_REPO_ROOT = _HERE.parent.parent  # racine du projet jardin/
DEFAULT_DB = _REPO_ROOT / "data" / "jardin.db"
DEFAULT_SAINTS_JSON = _HERE / "saints_du_jour.json"
DEFAULT_DICTONS_JSON = _HERE / "dictons_du_jour.json"


# ─────────────────────────────────────────────
# Schémas SQL attendus par la webapp
# ─────────────────────────────────────────────

SQL_CREATE_SAINT_DU_JOUR = """
CREATE TABLE IF NOT EXISTS saint_du_jour (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    mois        INTEGER NOT NULL,
    jour        INTEGER NOT NULL,
    saints_json TEXT    NOT NULL DEFAULT '[]',
    source_url  TEXT,
    UNIQUE (mois, jour)
)
"""

SQL_CREATE_INDEX_SAINT = """
CREATE INDEX IF NOT EXISTS idx_saint_du_jour_mois_jour
    ON saint_du_jour (mois, jour)
"""

# La table dicton existe déjà dans la webapp (SQLModel).
# Colonnes: id, mois, jour, texte, region
# On s'assure juste qu'elle existe (ne recrée pas si déjà présente).
SQL_CREATE_DICTON = """
CREATE TABLE IF NOT EXISTS dicton (
    id     INTEGER PRIMARY KEY AUTOINCREMENT,
    mois   INTEGER NOT NULL,
    jour   INTEGER,
    texte  TEXT    NOT NULL,
    region TEXT
)
"""

SQL_CREATE_INDEX_DICTON = """
CREATE INDEX IF NOT EXISTS idx_dicton_mois_jour ON dicton (mois, jour)
"""


# ─────────────────────────────────────────────
# Chargement JSON
# ─────────────────────────────────────────────

def load_json(path: Path, label: str) -> list:
    if not path.exists():
        print(f"[ERREUR] Fichier introuvable : {path}", file=sys.stderr)
        sys.exit(1)
    with path.open(encoding="utf-8") as f:
        data = json.load(f)
    if not isinstance(data, list):
        print(f"[ERREUR] {label} : attendu une liste JSON, obtenu {type(data).__name__}", file=sys.stderr)
        sys.exit(1)
    print(f"  {label} : {len(data)} entrées chargées depuis {path.name}")
    return data


# ─────────────────────────────────────────────
# Import saints
# ─────────────────────────────────────────────

def import_saints(conn: sqlite3.Connection, data: list, mode: str, dry_run: bool) -> int:
    """Importe les saints dans saint_du_jour. Retourne le nombre d'entrées traitées."""
    conn.execute(SQL_CREATE_SAINT_DU_JOUR)
    conn.execute(SQL_CREATE_INDEX_SAINT)

    if mode == "replace" and not dry_run:
        conn.execute("DELETE FROM saint_du_jour")
        print("  [replace] saint_du_jour vidée")

    count = 0
    skipped = 0

    for entry in data:
        mois = entry.get("mois")
        jour = entry.get("jour")
        saints = entry.get("saints", [])
        source_url = entry.get("source_url")

        # Validation
        if not isinstance(mois, int) or not isinstance(jour, int):
            continue
        if not (1 <= mois <= 12 and 1 <= jour <= 31):
            continue

        # Normaliser en liste de strings non vides
        if isinstance(saints, str):
            saints = [saints]
        saints = [s.strip() for s in saints if isinstance(s, str) and s.strip()]
        saints_json = json.dumps(saints, ensure_ascii=False)

        if dry_run:
            count += 1
            continue

        if mode == "append":
            existing = conn.execute(
                "SELECT id FROM saint_du_jour WHERE mois=? AND jour=?", (mois, jour)
            ).fetchone()
            if existing:
                skipped += 1
                continue

        conn.execute(
            "INSERT OR REPLACE INTO saint_du_jour (mois, jour, saints_json, source_url) VALUES (?,?,?,?)",
            (mois, jour, saints_json, source_url),
        )
        count += 1

    if skipped:
        print(f"  saints ignorés (mode append, déjà présents) : {skipped}")
    return count


# ─────────────────────────────────────────────
# Import dictons
# ─────────────────────────────────────────────

def import_dictons(conn: sqlite3.Connection, data: list, mode: str, region: str | None, dry_run: bool) -> int:
    """Importe les dictons dans la table dicton. Retourne le nombre d'entrées insérées."""
    conn.execute(SQL_CREATE_DICTON)
    conn.execute(SQL_CREATE_INDEX_DICTON)

    if mode == "replace" and not dry_run:
        conn.execute("DELETE FROM dicton")
        print("  [replace] dicton vidée")

    count = 0

    for entry in data:
        mois = entry.get("mois")
        jour = entry.get("jour")  # peut être None
        dictons = entry.get("dictons", [])

        # Validation
        if not isinstance(mois, int):
            continue
        if not (1 <= mois <= 12):
            continue
        if jour is not None and not (1 <= jour <= 31):
            continue

        # Normaliser
        if isinstance(dictons, str):
            dictons = [dictons]
        dictons = [d.strip() for d in dictons if isinstance(d, str) and d.strip()]

        for texte in dictons:
            if dry_run:
                count += 1
                continue

            if mode == "append":
                existing = conn.execute(
                    "SELECT id FROM dicton WHERE mois=? AND jour IS ? AND texte=?",
                    (mois, jour, texte),
                ).fetchone()
                if existing:
                    continue

            conn.execute(
                "INSERT INTO dicton (mois, jour, texte, region) VALUES (?,?,?,?)",
                (mois, jour, texte, region),
            )
            count += 1

    return count


# ─────────────────────────────────────────────
# Point d'entrée
# ─────────────────────────────────────────────

def main():
    parser = argparse.ArgumentParser(
        description="Import saints et dictons dans la BDD webapp Jardin (indépendant de l'année)"
    )
    parser.add_argument("--db", default=str(DEFAULT_DB),
                        help=f"Chemin vers jardin.db (défaut: {DEFAULT_DB})")
    parser.add_argument("--saints-json", default=str(DEFAULT_SAINTS_JSON),
                        help=f"Fichier saints_du_jour.json (défaut: {DEFAULT_SAINTS_JSON.name})")
    parser.add_argument("--dictons-json", default=str(DEFAULT_DICTONS_JSON),
                        help=f"Fichier dictons_du_jour.json (défaut: {DEFAULT_DICTONS_JSON.name})")
    parser.add_argument("--mode", choices=["replace", "append"], default="replace",
                        help="replace = purge + recharge (défaut) | append = ajoute sans doublons")
    parser.add_argument("--only", choices=["saints", "dictons", "both"], default="both",
                        help="Importer uniquement saints, dictons, ou les deux (défaut: both)")
    parser.add_argument("--region", default=None,
                        help="Tag région pour les dictons (ex: 'Auvergne', 'National'). Vide = NULL")
    parser.add_argument("--dry-run", action="store_true",
                        help="Simulation : affiche les comptages sans modifier la BDD")
    args = parser.parse_args()

    db_path = Path(args.db)
    if not db_path.exists():
        print(f"[ERREUR] Base de données introuvable : {db_path}", file=sys.stderr)
        print("  → Vérifiez que la webapp a démarré au moins une fois pour créer la BDD.")
        sys.exit(1)

    region = args.region if args.region else None
    do_saints = args.only in ("saints", "both")
    do_dictons = args.only in ("dictons", "both")

    print(f"\n=== Import saints/dictons → {db_path} ===")
    print(f"  Mode  : {args.mode}")
    print(f"  Scope : {args.only}")
    if region:
        print(f"  Région: {region}")
    if args.dry_run:
        print("  *** DRY-RUN — aucune modification en BDD ***")
    print()

    # Charger les JSON nécessaires
    saints_data = load_json(Path(args.saints_json), "saints_du_jour") if do_saints else []
    dictons_data = load_json(Path(args.dictons_json), "dictons_du_jour") if do_dictons else []
    print()

    # Connexion SQLite
    conn = sqlite3.connect(str(db_path))
    conn.execute("PRAGMA journal_mode=WAL")
    conn.execute("PRAGMA foreign_keys=OFF")  # pas de cascade gestion manuelle

    saints_count = 0
    dictons_count = 0

    try:
        conn.execute("BEGIN")

        if do_saints:
            saints_count = import_saints(conn, saints_data, args.mode, args.dry_run)
        if do_dictons:
            dictons_count = import_dictons(conn, dictons_data, args.mode, region, args.dry_run)

        if not args.dry_run:
            conn.commit()
        else:
            conn.rollback()

    except Exception as exc:
        conn.rollback()
        print(f"\n[ERREUR] Transaction annulée : {exc}", file=sys.stderr)
        raise
    finally:
        conn.close()

    # Résumé
    print()
    print("=== Résultat ===")
    if do_saints:
        prefix = "[DRY-RUN] " if args.dry_run else ""
        print(f"  {prefix}Saints importés  : {saints_count} jours → table saint_du_jour")
    if do_dictons:
        prefix = "[DRY-RUN] " if args.dry_run else ""
        print(f"  {prefix}Dictons importés : {dictons_count} entrées → table dicton")
    print(f"  Base             : {db_path}")
    if args.dry_run:
        print("\n  → Relancez sans --dry-run pour appliquer les changements.")
    else:
        ts = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
        print(f"\n  Import terminé le {ts}")


if __name__ == "__main__":
    main()
