"""Module de transformation de texte via DeepSeek API + vérification Claude."""

import os
import re
import smtplib
from email.mime.text import MIMEText

import anthropic
import requests

import config


def send_credit_alert(platform: str, error_message: str):
    """Envoie un email d'alerte en cas de manque de crédits."""
    try:
        # Configuration email (à adapter selon ton fournisseur)
        sender = os.getenv("ALERT_EMAIL_FROM", "alert@mindfintech.com")
        recipient = os.getenv("ALERT_EMAIL_TO", "kevin@mindfintech.com")

        msg = MIMEText(f"""
Alerte MindFinTech Pipeline

Plateforme: {platform}
Erreur: {error_message}

Action requise: Recharger les crédits sur {platform}.
        """)
        msg["Subject"] = f"[MindFinTech] Crédits insuffisants - {platform}"
        msg["From"] = sender
        msg["To"] = recipient

        # Pour l'instant, on log juste l'alerte (configurer SMTP si besoin)
        print(f"⚠️ ALERTE CRÉDITS: {platform} - {error_message}")
        print(f"   Email serait envoyé à: {recipient}")

    except Exception as e:
        print(f"Erreur envoi alerte email: {e}")


class DeepSeekTransformer:
    """Transforme le texte en discours naturel via DeepSeek API + vérification Claude."""

    def __init__(self):
        if not config.DEEPSEEK_API_KEY:
            raise ValueError("DEEPSEEK_API_KEY non définie. Configurez-la dans .env")
        self.api_key = config.DEEPSEEK_API_KEY
        self.api_url = config.DEEPSEEK_API_URL
        self.model = config.DEEPSEEK_MODEL

        # Client Claude pour la vérification
        self.claude_client = None
        if config.ANTHROPIC_API_KEY:
            self.claude_client = anthropic.Anthropic(api_key=config.ANTHROPIC_API_KEY)

        # Cache des taux de change (mis à jour via web search)
        self.exchange_rates = None

    def _get_exchange_rates(self) -> dict:
        """Récupère les taux de change actuels via web search."""
        if self.exchange_rates:
            return self.exchange_rates

        if not self.claude_client:
            # Taux par défaut si pas de client Claude
            return {"GBP": 1.18, "USD": 0.92}

        try:
            print("      Recherche des taux de change actuels...")
            response = self.claude_client.messages.create(
                model="claude-sonnet-5",
                max_tokens=500,
                tools=[{
                    "type": "web_search_20250305",
                    "name": "web_search",
                    "max_uses": 2
                }],
                messages=[{
                    "role": "user",
                    "content": "Donne-moi les taux de change actuels: 1 GBP en EUR et 1 USD en EUR. Réponds UNIQUEMENT avec deux nombres décimaux séparés par une virgule, par exemple: 1.18,0.92"
                }]
            )

            # Extraire les taux de la réponse
            for block in response.content:
                if hasattr(block, 'text'):
                    text = block.text.strip()
                    # Chercher le pattern "X.XX,X.XX"
                    match = re.search(r'(\d+\.?\d*)\s*,\s*(\d+\.?\d*)', text)
                    if match:
                        gbp_rate = float(match.group(1))
                        usd_rate = float(match.group(2))
                        self.exchange_rates = {"GBP": gbp_rate, "USD": usd_rate}
                        print(f"      Taux: 1 GBP = {gbp_rate}€, 1 USD = {usd_rate}€")
                        return self.exchange_rates

            # Fallback si pas de match
            self.exchange_rates = {"GBP": 1.18, "USD": 0.92}
            return self.exchange_rates

        except Exception as e:
            print(f"      ⚠️ Erreur recherche taux: {e}, utilisation taux par défaut")
            self.exchange_rates = {"GBP": 1.18, "USD": 0.92}
            return self.exchange_rates

    def transform_to_speech(self, raw_text: str, title: str = "") -> str:
        """
        Transforme un texte brut de newsletter en script audio naturel.
        Passe 1: DeepSeek pour la transformation
        Passe 2: Claude Sonnet 5 pour la vérification technique + chiffres (avec taux de change web search)
        Passe 3: Claude Sonnet 5 pour les émotions et Audio Tags ElevenLabs v3
        Passe 4: Claude Sonnet 5 pour la vérification écoute/cohérence
        """
        # Récupérer les taux de change actuels (cache pour toutes les passes)
        if self.claude_client:
            self._get_exchange_rates()

        # Première passe : transformation avec DeepSeek
        print("   Passe 1/4: DeepSeek (transformation)...")
        script_v1 = self._first_pass_deepseek(raw_text, title)

        # Deuxième passe : vérification technique avec Claude Sonnet 5
        if self.claude_client:
            print("   Passe 2/4: Claude Sonnet 5 (vérification technique + chiffres)...")
            script_v2 = self._second_pass_claude(script_v1, raw_text)

            # Troisième passe : émotions et Audio Tags v3
            print("   Passe 3/4: Claude Sonnet 5 (émotions + Audio Tags)...")
            script_v3 = self._third_pass_emotions(script_v2)

            # Quatrième passe : vérification écoute/cohérence avec Claude Sonnet 5
            print("   Passe 4/4: Claude Sonnet 5 (vérification écoute)...")
            script_final = self._fourth_pass_listening(script_v3)
        else:
            print("⚠️ Claude non configuré, vérifications ignorées")
            script_final = script_v1

        return script_final

    def _first_pass_deepseek(self, raw_text: str, title: str = "") -> str:
        """Première passe : transformation du texte brut en script avec DeepSeek."""
        date_match = re.search(r'(\d{1,2})\s+(\w+)\s+(\d{4})', title)
        if date_match:
            jour, mois, annee = date_match.groups()
            date_phrase = f"Nous sommes le {jour} {mois} {annee}, et voici ce qu'il faut retenir."
        else:
            date_phrase = "Voici les actualités du jour."

        prompt = f"""Tu es un podcasteur français professionnel en finance et tech.

TRANSFORME ce contenu en script de podcast audio FRANÇAIS NATUREL.

CONTRAINTE: Entre 350 et 480 mots (550 max)

STRUCTURE:
1. INTRO: "Bienvenue dans ta chronique news finance et tech françaises. ... {date_phrase}"

2. SOMMAIRE (juste après l'intro) - ÉNUMÉRER les points:
   "Au programme : ... Premier point, [sujet 1]. ... Deuxième point, [sujet 2]. ... Et troisième point, [sujet 3]."
   NOTE: NE PAS dire "aujourd'hui" ici, la date est déjà dans l'intro

3. CORPS - Chaque sujet en détail:
   - Utilise "..." (3 points) pour créer des PAUSES entre les sujets
   - 2-3 phrases max par sujet
   - Va à l'essentiel
   - AJOUTE les CONSÉQUENCES de chaque nouvelle - VARIE les formules:
     "Concrètement, cela signifie que...", "En clair, ...", "Autrement dit, ...",
     "Pour l'utilisateur, ça veut dire...", "Pour les entreprises, cela implique...",
     "Ce que ça change : ...", "Résultat : ...", "En pratique, ..."

4. OUTRO (pas de résumé, le sommaire est déjà au début) - VARIE entre ces formules:
   - "... Voilà, c'est tout pour aujourd'hui. ... Abonne-toi pour ne rien manquer. ... À demain."
   - "... C'est terminé pour cette édition. ... Retrouve-nous demain pour la suite de l'actu."
   - "... On se retrouve demain pour un nouveau point sur l'actualité. ... Bonne journée."
   - "... Merci de nous avoir écoutés. ... Rendez-vous demain pour la suite."

CHIFFRES:
- ARRONDIS: 200 millions (pas 206), 1 milliard (pas 1,24)
- MAX 2-3 chiffres par sujet
- Préfère: "a doublé", "+50%" plutôt que montants précis
- Convertis TOUT en euros (pas de livres, dollars)
- Utilise MAJUSCULES pour les chiffres importants: "C'est ÉNORME" ou "200 MILLIONS d'euros"

STYLE:
- Français courant, PAS de mots familiers ou vulgaires
- Vocabulaire simple (pas "brèves", "préjudice", "conjoncture")
- EXPLIQUE les termes financiers techniques pour que tout le monde comprenne
  (ex: "le SCT Inst, c'est le virement instantané", "la fintech, une startup de la finance")
- Pas de mots de remplissage ("bref", "en gros", "du coup")
- Tutoiement au début et à la fin, sinon ton impersonnel et professionnel dans le corps
- NE MENTIONNE JAMAIS "mind" ou "mindFintech"

CONTENU:
{raw_text}

SCRIPT:"""

        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
        }

        payload = {
            "model": self.model,
            "messages": [
                {"role": "system", "content": "Tu es un podcasteur français expert en finance. Style naturel et accessible."},
                {"role": "user", "content": prompt}
            ],
            "temperature": 0.7,
            "max_tokens": 4000,
        }

        try:
            response = requests.post(self.api_url, headers=headers, json=payload, timeout=90)

            # Vérifier les erreurs de crédits
            if response.status_code == 402 or "insufficient" in response.text.lower() or "credit" in response.text.lower():
                send_credit_alert("DeepSeek", f"Crédits insuffisants: {response.text[:200]}")
                raise ValueError(f"Crédits DeepSeek insuffisants")

            response.raise_for_status()
            result = response.json()

            if "choices" in result and len(result["choices"]) > 0:
                return result["choices"][0]["message"]["content"].strip()

        except requests.exceptions.RequestException as e:
            if "402" in str(e) or "credit" in str(e).lower():
                send_credit_alert("DeepSeek", str(e))
            raise

        return raw_text

    def _second_pass_claude(self, script: str, raw_text: str = "") -> str:
        """Deuxième passe : vérification technique + ton émotionnel avec Claude Sonnet 5."""

        # Récupérer les taux de change actuels via web search
        rates = self._get_exchange_rates()
        gbp_rate = rates.get("GBP", 1.18)
        usd_rate = rates.get("USD", 0.92)

        prompt = f"""Tu es un relecteur expert de podcasts audio français.

VÉRIFIE ce script par rapport au TEXTE ORIGINAL et corrige si nécessaire.

TEXTE ORIGINAL (source):
{raw_text}

---

SCRIPT À VÉRIFIER:
{script}

---

VÉRIFICATIONS PAR RAPPORT À L'ORIGINAL:
1. EXACTITUDE DES INFORMATIONS - Compare avec le texte original:
   - Les chiffres sont-ils corrects et fidèles à la source?
   - Les noms propres (entreprises, personnes) sont-ils exacts?
   - Les faits sont-ils fidèlement rapportés?
   - Aucune information inventée ou déformée

2. TON JOURNALISTIQUE - TRÈS IMPORTANT:
   C'est un podcast de NEWS SÉRIEUX. Ton PROFESSIONNEL et FACTUEL.

   Pour CHAQUE news, identifie si c'est:
   - NOUVELLE POSITIVE: levée de fonds, croissance, partenariat
     → Ton factuel, pas enthousiaste
     → Mots sobres: "annonce", "progression", "développement"
   - NOUVELLE NÉGATIVE: perte, échec, licenciements, rachat avorté
     → Ton sobre et mesuré
     → Mots factuels: "abandon du projet", "difficultés", "recul"
   - NEWS NEUTRE: changement, nomination, réglementation
     → Ton informatif et factuel

   COHÉRENCE:
   - Si tu qualifies une news de positive → ce qui suit doit l'être
   - Si tu qualifies une news de négative → ce qui suit doit l'être
   - ÉVITE les superlatifs ("extraordinaire", "incroyable", "fantastique")

3. CONSÉQUENCES - CRITIQUE:
   - Vérifie que les conséquences mentionnées sont LOGIQUES et COHÉRENTES
   - Les conséquences découlent-elles vraiment des faits annoncés?
   - Pas de conséquences inventées ou exagérées
   - Si une conséquence n'a pas de sens, SUPPRIME-LA ou CORRIGE-LA

4. CHIFFRES - CRITIQUE:
   - Garde UNIQUEMENT les chiffres NÉCESSAIRES à la compréhension
   - Vérifie qu'ils correspondent à l'original
   - Préfère "a doublé", "en forte hausse", "+50%" aux montants exacts
   - Max 2-3 chiffres par sujet, arrondis
   - Utilise MAJUSCULES pour les chiffres importants: "200 MILLIONS d'euros"
   - Ajoute "..." après les gros chiffres pour marquer une pause

5. CONVERSION EUROS (TAUX ACTUELS DU JOUR):
   - SCAN pour: "livres", "livre", "£", "dollars", "dollar", "$", "sterling", "GBP", "USD"
   - TAUX ACTUELS: 1 livre = {gbp_rate}€, 1 dollar = {usd_rate}€
   - CONVERTIS en euros arrondis avec ces taux
   - INTERDICTION de laisser d'autres devises dans le texte final

AUTRES VÉRIFICATIONS:
- Entre 350 et 480 mots (550 max)
- PAS de résumé à la fin (sommaire au début suffit)
- PAS de répétitions
- Fluidité et transitions logiques
- Français courant, pas de mots familiers
- Utilise "..." entre chaque sujet pour créer des pauses naturelles
- Outro: garde la variante choisie par DeepSeek (ne pas modifier)

RENVOIE UNIQUEMENT LE SCRIPT CORRIGÉ, sans commentaires ni analyse:"""

        try:
            message = self.claude_client.messages.create(
                model="claude-sonnet-5",
                max_tokens=4000,
                messages=[{"role": "user", "content": prompt}]
            )

            # Extraire le texte (ignorer ThinkingBlock)
            for block in message.content:
                if hasattr(block, 'text'):
                    return block.text.strip()

            return script

        except anthropic.APIStatusError as e:
            # Vérifier les erreurs de crédits
            if e.status_code == 402 or "credit" in str(e).lower() or "insufficient" in str(e).lower():
                send_credit_alert("Claude/Anthropic (Sonnet)", str(e))
            raise
        except Exception as e:
            if "credit" in str(e).lower() or "insufficient" in str(e).lower():
                send_credit_alert("Claude/Anthropic (Sonnet)", str(e))
            print(f"⚠️ Erreur vérification Claude Sonnet: {e}")
            return script

    def _third_pass_emotions(self, script: str) -> str:
        """Troisième passe : ajout subtil d'émotions avec Audio Tags ElevenLabs v3."""

        prompt = f"""Tu es un journaliste radio professionnel spécialisé en finance et tech.

C'est un podcast de NEWS SÉRIEUX. Le ton doit rester PROFESSIONNEL et CRÉDIBLE.

ELEVENLABS V3 utilise des AUDIO TAGS entre crochets (PAS de SSML).

=== AUDIO TAGS AUTORISÉS (UTILISATION SOBRE) ===

TON PROFESSIONNEL:
- [serious] : ton grave pour les infos importantes ou négatives
- [thoughtful] : réflexion, analyse

SUBTILITÉ ÉMOTIONNELLE (avec parcimonie):
- [sighs] : UNIQUEMENT avant une mauvaise nouvelle significative (1 max par épisode)
- [clears throat] : transition vers un nouveau sujet (1-2 max)

INTERDIT dans ce contexte professionnel:
- [excited], [happy], [surprised], [laughing], [chuckles] → trop informel pour un podcast news
- [sad], [annoyed] → trop émotionnel

=== TECHNIQUES DE PONCTUATION ===

- MAJUSCULES pour les chiffres clés: "200 MILLIONS d'euros", "1 MILLIARD"
- "..." pour les pauses naturelles entre les idées
- "—" pour une pause mid-phrase élégante

=== PLACEMENT DES TAGS (MAX 3-4 AU TOTAL) ===

1. MAUVAISE NOUVELLE importante:
   "[sighs] Le projet a finalement été abandonné..."
   OU simplement: "[serious] Le projet a été abandonné."

2. TRANSITION entre sujets:
   "... [clears throat] Passons à notre deuxième sujet."

3. ANALYSE/CONSÉQUENCE:
   "[thoughtful] Concrètement, cela signifie que..."

=== RÈGLES STRICTES ===

- MAXIMUM 3-4 audio tags par épisode (sobriété)
- TON JOURNALISTIQUE: informatif, factuel, crédible
- PAS d'exclamations excessives "!"
- PAS de ton enthousiaste ou joyeux
- AUCUN SSML (<break>, <prosody>, etc.)
- Les MAJUSCULES uniquement sur les chiffres importants

=== SCRIPT À ENRICHIR ===

{script}

RENVOIE UNIQUEMENT LE SCRIPT avec les ajustements sobres, sans commentaires:"""

        try:
            message = self.claude_client.messages.create(
                model="claude-sonnet-5",
                max_tokens=4000,
                messages=[{"role": "user", "content": prompt}]
            )

            # Extraire le texte (ignorer ThinkingBlock)
            for block in message.content:
                if hasattr(block, 'text'):
                    return block.text.strip()

            return script

        except anthropic.APIStatusError as e:
            if e.status_code == 402 or "credit" in str(e).lower() or "insufficient" in str(e).lower():
                send_credit_alert("Claude/Anthropic (Sonnet)", str(e))
            raise
        except Exception as e:
            if "credit" in str(e).lower() or "insufficient" in str(e).lower():
                send_credit_alert("Claude/Anthropic (Sonnet)", str(e))
            print(f"⚠️ Erreur ajout émotions Claude Sonnet: {e}")
            return script

    def _fourth_pass_listening(self, script: str) -> str:
        """Quatrième passe : vérification écoute et cohérence avec Claude Sonnet 5."""

        prompt = f"""Tu es un auditeur de podcast qui écoute dans les transports ou en voiture.

VÉRIFIE que ce script est FACILE À ÉCOUTER et COHÉRENT.

CRITÈRES D'ÉCOUTE FACILE:
1. PHRASES COURTES: Facile à suivre en conduisant ou dans le métro
2. TRANSITIONS CLAIRES: On comprend quand on change de sujet
3. VOCABULAIRE SIMPLE: Pas de jargon technique non expliqué
4. FRANÇAIS COURANT: Pas de mots familiers, vulgaires ou trop soutenus

COHÉRENCE À VÉRIFIER:
1. Si on dit "bonne nouvelle" → ce qui suit doit être positif
2. Si on dit "mauvaise nouvelle" ou "point noir" → ce qui suit doit être négatif
3. Si on mentionne un pays/continent → vérifier que c'est cohérent avec l'entreprise
4. Les chiffres doivent être logiques (pas de contradiction)
5. DEVISES: Vérifie qu'il n'y a PAS de "livres", "dollars", "£", "$" - TOUT doit être en euros

VÉRIFICATION AUDIO TAGS (ElevenLabs v3):
1. MAX 3-4 audio tags au total (sobriété professionnelle)
2. Tags autorisés: [serious], [thoughtful], [sighs], [clears throat]
3. Tags INTERDITS: [excited], [happy], [surprised], [laughing] (trop informel)
4. Pas de SSML (<break>, <prosody>) - uniquement des [audio tags]
5. Les "..." sont utilisés pour les pauses naturelles
6. Les MAJUSCULES uniquement sur les chiffres clés

IMPORTANT:
- Garde le script SIMPLE et NATUREL
- Ne complexifie PAS, simplifie si besoin
- Garde l'intro et l'outro EXACTEMENT comme elles sont
- Entre 350 et 480 mots (550 max)
- PAS de résumé à la fin (le sommaire est au début)
- SUPPRIME tout SSML restant (<break>, <prosody>, <emphasis>)

SCRIPT À VÉRIFIER:
{script}

RENVOIE UNIQUEMENT LE SCRIPT CORRIGÉ, sans commentaires ni analyse:"""

        try:
            message = self.claude_client.messages.create(
                model="claude-sonnet-5",
                max_tokens=4000,
                messages=[{"role": "user", "content": prompt}]
            )

            # Extraire le texte (ignorer ThinkingBlock)
            for block in message.content:
                if hasattr(block, 'text'):
                    return block.text.strip()

            return script

        except anthropic.APIStatusError as e:
            if e.status_code == 402 or "credit" in str(e).lower() or "insufficient" in str(e).lower():
                send_credit_alert("Claude/Anthropic (Sonnet)", str(e))
            raise
        except Exception as e:
            if "credit" in str(e).lower() or "insufficient" in str(e).lower():
                send_credit_alert("Claude/Anthropic (Sonnet)", str(e))
            print(f"⚠️ Erreur vérification Claude Sonnet: {e}")
            return script
