#!/usr/bin/env python3
"""
Pipeline Newsletter-to-Podcast

Orchestrateur principal qui:
1. Récupère les newsletters non traitées depuis Gmail
2. Extrait et nettoie le contenu
3. Génère l'audio via ElevenLabs
4. Upload sur YouTube
5. Marque les emails comme traités
"""

import argparse
import re
import sys
from datetime import datetime

from modules import GmailFilter, ContentExtractor, TextToSpeech, YouTubeUploader, CleanFlux, DeepSeekTransformer
import config


def extract_newsletter_date(text: str) -> str:
    """Extrait la date de la newsletter depuis le contenu."""
    # Chercher le pattern: mind Fintech <newsletter@groupe-mind.com> suivi de Date:
    # ou directement From: mind Fintech ... Date:
    patterns = [
        r'mind\s+Fintech[^D]*Date:\s*([^\n]+)',  # mind Fintech ... Date:
        r'newsletter@groupe-mind\.com[>\s]*\n?Date:\s*([^\n]+)',  # email suivi de Date:
    ]

    for pattern in patterns:
        match = re.search(pattern, text, re.IGNORECASE)
        if match:
            date_str = match.group(1).strip()
            # Parser la date: "Tue, 8 Sept 2026 at 18:01"
            date_match = re.search(r'(\d{1,2})\s+(\w+)\s+(\d{4})', date_str)
            if date_match:
                day, month, year = date_match.groups()
                # Convertir le mois en nombre
                months = {
                    'jan': '01', 'janvier': '01',
                    'fev': '02', 'feb': '02', 'février': '02', 'fevrier': '02',
                    'mar': '03', 'mars': '03',
                    'avr': '04', 'apr': '04', 'avril': '04',
                    'mai': '05', 'may': '05',
                    'jun': '06', 'juin': '06',
                    'jui': '07', 'jul': '07', 'juillet': '07',
                    'aou': '08', 'aug': '08', 'août': '08', 'aout': '08',
                    'sep': '09', 'sept': '09', 'septembre': '09',
                    'oct': '10', 'octobre': '10',
                    'nov': '11', 'novembre': '11',
                    'dec': '12', 'décembre': '12', 'decembre': '12'
                }
                month_lower = month.lower()
                month_num = months.get(month_lower, months.get(month_lower[:3], '00'))
                return f"{year}-{month_num}-{day.zfill(2)}"

    # Fallback: date du jour
    return datetime.now().strftime("%Y-%m-%d")


def get_newsletter_filename(text: str, subject: str) -> str:
    """Génère un nom de fichier basé sur la date et le sujet de la newsletter.

    Format: YYYY-MM-DD_Sujet_Nettoye
    Exemple: 2026-09-08_Briefing_Instant_Payment_Funding_Circle
    """
    date = extract_newsletter_date(text)

    # Extraire le sujet entre crochets s'il existe: [Briefing] Instant Payment | Funding Circle
    bracket_match = re.search(r'\[([^\]]+)\]\s*(.+)', subject)
    if bracket_match:
        prefix = bracket_match.group(1).strip()  # "Briefing"
        rest = bracket_match.group(2).strip()    # "Instant Payment | Funding Circle"
        clean_subject = f"{prefix}_{rest}"
    else:
        clean_subject = subject

    # Nettoyer: enlever caractères spéciaux, remplacer espaces et | par _
    clean_subject = re.sub(r'[|:,;!?\[\](){}]', '', clean_subject)
    clean_subject = re.sub(r'\s+', '_', clean_subject.strip())
    clean_subject = re.sub(r'_+', '_', clean_subject)  # Éviter les __ multiples
    clean_subject = clean_subject.strip('_')[:60]  # Limiter la longueur

    return f"{date}_{clean_subject}"


def is_already_processed(filename: str) -> bool:
    """Vérifie si une newsletter a déjà été traitée localement."""
    raw_file = config.OUTPUT_RAW_DIR / f"{filename}_raw.txt"
    audio_file = config.OUTPUT_AUDIO_DIR / f"{filename}_audio.mp3"
    return raw_file.exists() or audio_file.exists()


def save_raw_text(filename: str, title: str, raw_text: str) -> str:
    """Sauvegarde le texte brut extrait."""
    text_file = config.OUTPUT_RAW_DIR / f"{filename}_raw.txt"
    content = f"# {title}\n\n{raw_text}"
    with open(text_file, "w", encoding="utf-8") as f:
        f.write(content)
    return str(text_file)


def save_clean_text(filename: str, title: str, script: str, model: str = "") -> str:
    """Sauvegarde le script nettoyé pour TTS.

    Args:
        filename: Nom de base (date_sujet)
        title: Titre de la newsletter
        script: Script transformé
        model: Nom du modèle utilisé (ex: deepseek-chat, claude-opus-5)
    """
    if model:
        text_file = config.OUTPUT_CLEAN_DIR / f"{filename}_clean_{model}.txt"
    else:
        text_file = config.OUTPUT_CLEAN_DIR / f"{filename}_clean.txt"
    with open(text_file, "w", encoding="utf-8") as f:
        f.write(script)
    return str(text_file)


def process_newsletter(email_data: dict, dry_run: bool = False) -> dict:
    """Traite une newsletter complète."""
    result = {
        "email_id": email_data["id"],
        "filename": None,
        "subject": email_data["subject"],
        "status": "pending",
        "raw_path": None,
        "clean_path": None,
        "audio_path": None,
        "youtube_url": None,
        "error": None,
    }

    try:
        # Étape 0: Extraction initiale pour obtenir la date
        print(f"\n{'='*60}")
        print(f"Traitement: {email_data['subject']}")
        print(f"{'='*60}")

        extractor = ContentExtractor()

        # Extraire le texte brut
        raw_text = extractor.extract_text(
            email_data.get("body_html", ""),
            email_data.get("body_text", ""),
        )

        if not raw_text.strip():
            result["status"] = "skipped"
            result["error"] = "Contenu vide après extraction"
            print("⚠ Contenu vide, email ignoré")
            return result

        print(f"✓ Contenu extrait ({len(raw_text)} caractères)")

        # Générer le nom de fichier basé sur la date de la newsletter
        filename = get_newsletter_filename(raw_text, email_data["subject"])
        result["filename"] = filename
        print(f"✓ Fichier: {filename}")

        # Vérifier si déjà traité
        if is_already_processed(filename):
            result["status"] = "skipped"
            result["error"] = "Déjà traité (fichier local existant)"
            print("⚠ Newsletter déjà traitée localement, ignorée")
            return result

        # Générer le titre
        title = extractor.generate_title(email_data["subject"], email_data["date"])

        # Sauvegarder le texte brut
        raw_path = save_raw_text(filename, title, raw_text)
        result["raw_path"] = raw_path
        print(f"✓ Texte brut sauvegardé: {raw_path}")

        # Transformer en script audio
        # Priorité: 1. CleanFlux (défaut) → 2. DeepSeek (fallback) → 3. Local
        script = None
        model_used = ""

        # Option 1: CleanFlux (défaut)
        if config.CLEANFLUX_API_KEY and not script:
            try:
                print("Transformation du texte avec CleanFlux...")
                cleanflux = CleanFlux()
                clean_text = cleanflux.clean_for_speech(raw_text)
                script = extractor.to_speech_script(clean_text, email_data["subject"])
                model_used = "cleanflux"
                print(f"✓ Script généré par CleanFlux ({len(script)} caractères)")
            except Exception as e:
                print(f"⚠ CleanFlux indisponible ({e})")

        # Option 2: DeepSeek (fallback)
        if config.DEEPSEEK_API_KEY and not script:
            try:
                print("Transformation du texte avec DeepSeek...")
                transformer = DeepSeekTransformer()
                script = transformer.transform_to_speech(raw_text, title)
                model_used = "deepseek-chat"
                print(f"✓ Script généré par DeepSeek ({len(script)} caractères)")
            except Exception as e:
                print(f"⚠ DeepSeek indisponible ({e})")

        # Option 3: Transformation locale (dernier recours)
        if not script:
            print("Transformation locale du texte...")
            script = extractor.to_speech_script(raw_text, email_data["subject"])
            model_used = "local"
            print(f"✓ Script généré localement ({len(script)} caractères)")

        # Sauvegarder le script nettoyé
        clean_path = save_clean_text(filename, title, script, model_used)
        result["clean_path"] = clean_path
        print(f"✓ Script sauvegardé: {clean_path}")

        # Générer la description pour YouTube
        description = extractor.generate_description(script)

        if dry_run:
            print(f"\n[DRY RUN] Titre: {title}")
            print(f"[DRY RUN] Script (extrait): {script[:500]}...")
            result["status"] = "dry_run"
            return result

        # Étape 2: Génération audio
        print("Génération de l'audio...")
        tts = TextToSpeech()

        audio_path = tts.generate_audio(script, f"{filename}_audio")
        result["audio_path"] = str(audio_path)
        print(f"✓ Audio généré: {audio_path}")

        # Audio prêt pour YouTube Music / Spotify
        result["status"] = "success"
        print(f"✓ Prêt pour distribution (YouTube Music, Spotify, etc.)")

        # Étape 3: Upload YouTube (optionnel, désactivé par défaut)
        if config.YOUTUBE_ENABLED:
            print("Upload sur YouTube...")
            youtube = YouTubeUploader()
            youtube.authenticate()

            upload_result = youtube.upload_audio_as_video(
                audio_path=audio_path,
                title=title,
                description=description,
            )

            result["youtube_url"] = upload_result["url"]
            print(f"✓ Vidéo uploadée: {upload_result['url']}")
            print(f"  Visibilité: {upload_result['status']}")

    except Exception as e:
        result["status"] = "error"
        result["error"] = str(e)
        print(f"✗ Erreur: {e}")

    return result


def run_pipeline(max_emails: int = 10, dry_run: bool = False) -> list[dict]:
    """Exécute le pipeline complet."""
    print("\n" + "=" * 60)
    print("PIPELINE NEWSLETTER-TO-PODCAST")
    print("=" * 60)

    results = []

    # Connexion Gmail
    print("\n1. Connexion à Gmail...")
    gmail = GmailFilter()
    gmail.authenticate()
    print("✓ Connecté à Gmail")

    # Récupération des newsletters
    print(f"\n2. Recherche des newsletters ({config.GMAIL_FILTER_ADDRESS})...")
    emails = gmail.get_unprocessed_newsletters(max_results=max_emails)
    print(f"✓ {len(emails)} newsletter(s) non traitée(s) trouvée(s)")

    if not emails:
        print("\nAucune nouvelle newsletter à traiter.")
        return results

    # Traitement de chaque email
    print(f"\n3. Traitement des newsletters...")
    for i, email in enumerate(emails, 1):
        print(f"\n[{i}/{len(emails)}]")

        result = process_newsletter(email, dry_run=dry_run)
        results.append(result)

        # Marquer comme traité si succès
        if result["status"] == "success" and not dry_run:
            gmail.mark_as_processed(email["id"])
            print("✓ Email marqué comme traité")

    # Résumé
    print("\n" + "=" * 60)
    print("RÉSUMÉ")
    print("=" * 60)

    success = sum(1 for r in results if r["status"] == "success")
    errors = sum(1 for r in results if r["status"] == "error")
    skipped = sum(1 for r in results if r["status"] == "skipped")

    print(f"Traités avec succès: {success}")
    print(f"Erreurs: {errors}")
    print(f"Ignorés: {skipped}")

    if errors > 0:
        print("\nDétail des erreurs:")
        for r in results:
            if r["status"] == "error":
                print(f"  - {r['subject']}: {r['error']}")

    # Générer le flux RSS si des épisodes ont été créés
    if success > 0 and not dry_run:
        print("\n" + "=" * 60)
        print("GÉNÉRATION DU FLUX RSS")
        print("=" * 60)
        try:
            from modules.rss_generator import RSSGenerator
            rss = RSSGenerator()
            feed_path = rss.generate_feed()
            if feed_path:
                print(f"✓ Flux RSS disponible: {feed_path}")
        except Exception as e:
            print(f"⚠ Erreur génération RSS: {e}")

    return results


def main():
    """Point d'entrée principal."""
    parser = argparse.ArgumentParser(
        description="Pipeline de conversion newsletter vers podcast YouTube"
    )
    parser.add_argument(
        "--max-emails",
        type=int,
        default=10,
        help="Nombre maximum d'emails à traiter (défaut: 10)",
    )
    parser.add_argument(
        "--dry-run",
        action="store_true",
        help="Mode test: extrait le contenu sans générer audio/upload",
    )

    args = parser.parse_args()

    try:
        results = run_pipeline(
            max_emails=args.max_emails,
            dry_run=args.dry_run,
        )
        # Exit code basé sur les résultats
        if any(r["status"] == "error" for r in results):
            sys.exit(1)
    except KeyboardInterrupt:
        print("\n\nInterrompu par l'utilisateur.")
        sys.exit(130)
    except Exception as e:
        print(f"\nErreur fatale: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()
