"""
DarkFactory - Pipeline de Videos Faceless & Dark Channels.
Pipeline end-to-end: tema -> roteiro -> narracao -> footage -> edicao -> thumbnail.
"""

import json
import logging
import re
import os
import uuid
import asyncio
from datetime import datetime, timedelta
from pathlib import Path

from sqlalchemy.orm import Session
from sqlalchemy import func, desc

from backend.models.video import Video

logger = logging.getLogger(__name__)

# Pipeline status tracking (in-memory for now)
_pipelines: dict = {}

# Supported niches with RPM data
DARK_NICHES = {
    "curiosidades": {"rpm": 4.0, "avg_length": "8-12 min", "style": "narration + stock footage"},
    "historia": {"rpm": 6.0, "avg_length": "10-15 min", "style": "narration + historical images"},
    "ciencia": {"rpm": 5.0, "avg_length": "8-12 min", "style": "narration + animations"},
    "true_crime": {"rpm": 8.0, "avg_length": "15-25 min", "style": "narration + dramatic footage"},
    "tecnologia": {"rpm": 7.0, "avg_length": "8-12 min", "style": "narration + screen recordings"},
    "financas": {"rpm": 12.0, "avg_length": "10-15 min", "style": "narration + charts"},
    "motivacional": {"rpm": 3.5, "avg_length": "5-10 min", "style": "narration + cinematic footage"},
    "top_listas": {"rpm": 4.5, "avg_length": "10-15 min", "style": "countdown + stock footage"},
    "misterios": {"rpm": 6.5, "avg_length": "12-20 min", "style": "narration + atmospheric"},
    "saude": {"rpm": 5.5, "avg_length": "8-12 min", "style": "narration + medical illustrations"},
}

# Voice options for TTS
VOICE_OPTIONS = {
    "pt-BR-AntonioNeural": {"lang": "pt-BR", "gender": "male", "style": "narration"},
    "pt-BR-FranciscaNeural": {"lang": "pt-BR", "gender": "female", "style": "narration"},
    "pt-BR-ThalitaNeural": {"lang": "pt-BR", "gender": "female", "style": "conversational"},
    "en-US-GuyNeural": {"lang": "en-US", "gender": "male", "style": "narration"},
    "en-US-JennyNeural": {"lang": "en-US", "gender": "female", "style": "narration"},
    "es-ES-AlvaroNeural": {"lang": "es-ES", "gender": "male", "style": "narration"},
}

# Niche-specific script templates
NICHE_PROMPTS = {
    "curiosidades": (
        "Voce e um roteirista profissional de canais de curiosidades no YouTube. "
        "Escreva de forma envolvente, usando frases curtas e impactantes. "
        "Inclua fatos surpreendentes e mantenha o espectador curioso o tempo todo."
    ),
    "historia": (
        "Voce e um historiador e narrador profissional. "
        "Conte a historia de forma dramatica e cinematica, como um documentario. "
        "Use detalhes vividos e crie uma narrativa envolvente."
    ),
    "ciencia": (
        "Voce e um divulgador cientifico que explica conceitos complexos de forma simples. "
        "Use analogias do cotidiano e mantenha o tom acessivel mas preciso."
    ),
    "true_crime": (
        "Voce e um narrador de true crime profissional. "
        "Crie suspense, use detalhes investigativos e mantenha o espectador preso ate o final. "
        "Tom serio e respeitoso com as vitimas."
    ),
    "tecnologia": (
        "Voce e um especialista em tecnologia que explica inovacoes de forma clara. "
        "Foque no impacto pratico e nas implicacoes futuras. Tom moderno e entusiasmado."
    ),
    "financas": (
        "Voce e um educador financeiro que simplifica conceitos de investimento e economia. "
        "Use exemplos praticos com numeros reais. Tom confiante e didatico."
    ),
    "motivacional": (
        "Voce e um palestrante motivacional. Escreva de forma inspiradora e emotiva. "
        "Use historias de superacao e frases de impacto. Tom energetico e positivo."
    ),
    "top_listas": (
        "Voce cria listas top de forma envolvente. Cada item deve ter uma revelacao surpreendente. "
        "Use contagem regressiva para manter a tensao. O numero 1 deve ser impactante."
    ),
    "misterios": (
        "Voce e um narrador de misterios e fenomenos inexplicados. "
        "Crie uma atmosfera tensa, use perguntas retoricas e deixe o espectador pensando."
    ),
    "saude": (
        "Voce e um profissional de saude que explica temas medicos de forma acessivel. "
        "Use linguagem simples, cite pesquisas e de dicas praticas."
    ),
}


def _generate_pipeline_id() -> str:
    """Generate a unique pipeline ID."""
    return f"pipe_{datetime.utcnow().strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4().hex[:8]}"


def _estimate_word_count(duration_minutes: int) -> int:
    """Estimate word count for narration based on duration.
    Average speaking rate: ~150 words/minute for narration.
    """
    return int(duration_minutes * 150)


def _extract_json_from_response(text: str) -> dict:
    """Extract JSON from LLM response, handling markdown code blocks."""
    if not text:
        return {}
    # Try to find JSON in code blocks
    json_match = re.search(r'```(?:json)?\s*\n?(.*?)\n?```', text, re.DOTALL)
    if json_match:
        text = json_match.group(1).strip()
    # Try direct parse
    try:
        return json.loads(text)
    except json.JSONDecodeError:
        pass
    # Try to find JSON object or array
    for pattern in [r'\{.*\}', r'\[.*\]']:
        match = re.search(pattern, text, re.DOTALL)
        if match:
            try:
                return json.loads(match.group(0))
            except json.JSONDecodeError:
                continue
    return {}


async def generate_video_pipeline(db: Session, topic: str, niche: str = "curiosidades",
                                    duration_minutes: int = 10, voice: str = "pt-BR-AntonioNeural",
                                    style: str = "cinematic") -> dict:
    """
    Start the full video pipeline: topic -> script -> narration -> footage -> assembly.
    Returns pipeline_id for tracking progress.
    """
    if niche not in DARK_NICHES:
        niche = "curiosidades"

    pipeline_id = _generate_pipeline_id()
    niche_info = DARK_NICHES[niche]

    _pipelines[pipeline_id] = {
        "id": pipeline_id,
        "topic": topic,
        "niche": niche,
        "niche_info": niche_info,
        "duration_minutes": duration_minutes,
        "voice": voice,
        "style": style,
        "status": "started",
        "progress": 0,
        "current_stage": "script",
        "stages": {
            "script": {"status": "pending", "started_at": None, "completed_at": None, "result": None},
            "narration": {"status": "pending", "started_at": None, "completed_at": None, "result": None},
            "footage": {"status": "pending", "started_at": None, "completed_at": None, "result": None},
            "thumbnail": {"status": "pending", "started_at": None, "completed_at": None, "result": None},
            "seo": {"status": "pending", "started_at": None, "completed_at": None, "result": None},
        },
        "created_at": datetime.utcnow().isoformat(),
        "updated_at": datetime.utcnow().isoformat(),
        "error": None,
    }

    # Run pipeline stages sequentially in background
    asyncio.create_task(_run_pipeline(pipeline_id, topic, niche, duration_minutes, voice, style))

    return {
        "pipeline_id": pipeline_id,
        "status": "started",
        "topic": topic,
        "niche": niche,
        "duration_minutes": duration_minutes,
        "estimated_time_minutes": _estimate_pipeline_time(duration_minutes),
        "stages": ["script", "narration", "footage", "thumbnail", "seo"],
    }


def _estimate_pipeline_time(duration_minutes: int) -> int:
    """Estimate total pipeline processing time in minutes."""
    script_time = 2  # LLM generation
    narration_time = max(1, duration_minutes // 3)  # TTS
    footage_time = 1  # API calls
    thumbnail_time = 1  # LLM prompt
    seo_time = 1  # LLM generation
    return script_time + narration_time + footage_time + thumbnail_time + seo_time


async def _run_pipeline(pipeline_id: str, topic: str, niche: str,
                         duration_minutes: int, voice: str, style: str):
    """Execute the full pipeline stages sequentially."""
    pipe = _pipelines.get(pipeline_id)
    if not pipe:
        return

    try:
        # Stage 1: Script Generation
        pipe["current_stage"] = "script"
        pipe["stages"]["script"]["status"] = "running"
        pipe["stages"]["script"]["started_at"] = datetime.utcnow().isoformat()
        pipe["progress"] = 10

        script_result = await generate_dark_script(topic, niche, duration_minutes, style)
        pipe["stages"]["script"]["status"] = "completed"
        pipe["stages"]["script"]["completed_at"] = datetime.utcnow().isoformat()
        pipe["stages"]["script"]["result"] = script_result
        pipe["progress"] = 30

        # Stage 2: Narration
        pipe["current_stage"] = "narration"
        pipe["stages"]["narration"]["status"] = "running"
        pipe["stages"]["narration"]["started_at"] = datetime.utcnow().isoformat()

        full_narration_text = ""
        if script_result.get("sections"):
            for section in script_result["sections"]:
                full_narration_text += section.get("narration", "") + "\n\n"
        elif script_result.get("full_script"):
            full_narration_text = script_result["full_script"]
        else:
            full_narration_text = f"Video sobre {topic} no nicho de {niche}."

        narration_result = await generate_narration(full_narration_text, voice)
        pipe["stages"]["narration"]["status"] = "completed"
        pipe["stages"]["narration"]["completed_at"] = datetime.utcnow().isoformat()
        pipe["stages"]["narration"]["result"] = narration_result
        pipe["progress"] = 55

        # Stage 3: Footage Selection
        pipe["current_stage"] = "footage"
        pipe["stages"]["footage"]["status"] = "running"
        pipe["stages"]["footage"]["started_at"] = datetime.utcnow().isoformat()

        keywords = script_result.get("tags", [topic])
        if not keywords:
            keywords = [topic]
        footage_result = await select_stock_footage(keywords[:5], count=duration_minutes)
        pipe["stages"]["footage"]["status"] = "completed"
        pipe["stages"]["footage"]["completed_at"] = datetime.utcnow().isoformat()
        pipe["stages"]["footage"]["result"] = footage_result
        pipe["progress"] = 75

        # Stage 4: Thumbnail Prompt
        pipe["current_stage"] = "thumbnail"
        pipe["stages"]["thumbnail"]["status"] = "running"
        pipe["stages"]["thumbnail"]["started_at"] = datetime.utcnow().isoformat()

        title = script_result.get("title", topic)
        thumbnail_result = await generate_thumbnail_prompt(title, niche)
        pipe["stages"]["thumbnail"]["status"] = "completed"
        pipe["stages"]["thumbnail"]["completed_at"] = datetime.utcnow().isoformat()
        pipe["stages"]["thumbnail"]["result"] = thumbnail_result
        pipe["progress"] = 88

        # Stage 5: SEO Metadata
        pipe["current_stage"] = "seo"
        pipe["stages"]["seo"]["status"] = "running"
        pipe["stages"]["seo"]["started_at"] = datetime.utcnow().isoformat()

        summary = script_result.get("intro_hook", "")
        seo_result = await generate_seo_metadata(title, niche, summary)
        pipe["stages"]["seo"]["status"] = "completed"
        pipe["stages"]["seo"]["completed_at"] = datetime.utcnow().isoformat()
        pipe["stages"]["seo"]["result"] = seo_result
        pipe["progress"] = 100

        # All done
        pipe["status"] = "completed"
        pipe["current_stage"] = "done"
        pipe["updated_at"] = datetime.utcnow().isoformat()

    except Exception as e:
        logger.error(f"Pipeline {pipeline_id} failed: {e}")
        pipe["status"] = "failed"
        pipe["error"] = str(e)
        pipe["updated_at"] = datetime.utcnow().isoformat()
        # Mark current stage as failed
        current = pipe.get("current_stage", "")
        if current and current in pipe["stages"]:
            pipe["stages"][current]["status"] = "failed"


async def generate_dark_script(topic: str, niche: str = "curiosidades",
                                duration_minutes: int = 10, style: str = "informativo") -> dict:
    """
    Generate a long-form script for faceless videos using local LLM.
    Includes: title, intro_hook, sections (5-10 with narration + visual_direction),
    outro, seo_title, seo_description, tags.
    """
    from backend.services.local_ai import llm_chat

    if niche not in DARK_NICHES:
        niche = "curiosidades"

    word_count = _estimate_word_count(duration_minutes)
    num_sections = max(3, min(10, duration_minutes))
    words_per_section = word_count // num_sections

    system_prompt = NICHE_PROMPTS.get(niche, NICHE_PROMPTS["curiosidades"])

    user_prompt = f"""Crie um roteiro completo para um video faceless de YouTube sobre: "{topic}"

ESPECIFICACOES:
- Nicho: {niche}
- Duracao alvo: {duration_minutes} minutos (~{word_count} palavras de narracao)
- Estilo: {style}
- Numero de secoes: {num_sections}
- Palavras por secao: ~{words_per_section}

FORMATO DE SAIDA (JSON):
{{
    "title": "Titulo impactante do video (max 60 chars)",
    "intro_hook": "Frase de abertura que prende a atencao nos primeiros 5 segundos",
    "sections": [
        {{
            "number": 1,
            "subtitle": "Titulo da secao",
            "narration": "Texto completo da narracao desta secao (~{words_per_section} palavras). Escreva de forma envolvente e detalhada.",
            "visual_direction": "Descricao do que mostrar na tela: tipo de footage, transicoes, textos overlay",
            "duration_seconds": {(duration_minutes * 60) // num_sections}
        }}
    ],
    "outro": "Texto de encerramento com call to action para inscrever-se",
    "seo_title": "Titulo otimizado para SEO do YouTube (max 100 chars)",
    "seo_description": "Descricao do video para YouTube (200-300 palavras com keywords)",
    "tags": ["tag1", "tag2", "tag3", "tag4", "tag5", "tag6", "tag7", "tag8"],
    "full_script": "O roteiro completo concatenado (intro + todas as secoes + outro)"
}}

REGRAS:
1. O intro_hook DEVE ser impactante e criar curiosidade
2. Cada secao deve ter uma transicao natural para a proxima
3. Inclua dados, estatisticas ou fatos interessantes
4. O outro deve incentivar like, inscricao e comentario
5. Tags devem ser relevantes para SEO do YouTube
6. Escreva em portugues brasileiro
7. Retorne APENAS o JSON, sem texto adicional"""

    response = await llm_chat(
        prompt=user_prompt,
        system=system_prompt,
        max_tokens=4096,
        temperature=0.7,
    )

    result = _extract_json_from_response(response)

    # If LLM returned valid structured data, use it
    if result and "title" in result:
        # Ensure all required fields exist
        result.setdefault("intro_hook", f"Voce sabia que {topic}? O que vou revelar agora vai mudar tudo...")
        result.setdefault("sections", [])
        result.setdefault("outro", "Se voce gostou, deixe seu like e se inscreva no canal!")
        result.setdefault("seo_title", result.get("title", topic))
        result.setdefault("seo_description", f"Video sobre {topic} - {niche}")
        result.setdefault("tags", [topic, niche, "youtube", "faceless"])

        # Build full_script if not present
        if not result.get("full_script"):
            parts = [result.get("intro_hook", "")]
            for sec in result.get("sections", []):
                parts.append(sec.get("narration", ""))
            parts.append(result.get("outro", ""))
            result["full_script"] = "\n\n".join(p for p in parts if p)

        result["word_count"] = len(result.get("full_script", "").split())
        result["estimated_duration_minutes"] = max(1, result["word_count"] // 150)
        result["niche"] = niche
        result["style"] = style
        result["generated_at"] = datetime.utcnow().isoformat()
        return result

    # Fallback: build a structured script from raw text
    logger.warning("LLM did not return valid JSON, building fallback script")
    sections = []
    raw_text = response or f"Video sobre {topic} no nicho {niche}."
    paragraphs = [p.strip() for p in raw_text.split("\n\n") if p.strip()]

    for i, para in enumerate(paragraphs[:num_sections]):
        sections.append({
            "number": i + 1,
            "subtitle": f"Parte {i + 1}",
            "narration": para,
            "visual_direction": f"Stock footage relacionado a {topic}",
            "duration_seconds": (duration_minutes * 60) // max(1, len(paragraphs[:num_sections])),
        })

    full_script = "\n\n".join(p.get("narration", "") for p in sections)
    return {
        "title": f"{topic} - O que voce precisa saber",
        "intro_hook": f"Voce sabia que {topic}? Prepare-se para descobrir...",
        "sections": sections,
        "outro": "Se voce gostou desse conteudo, deixe seu like, se inscreva e ative o sininho!",
        "seo_title": f"{topic} | {niche.capitalize()} - Documentario Completo",
        "seo_description": f"Neste video, exploramos tudo sobre {topic}. Descubra fatos surpreendentes e informacoes que voce nao conhecia.",
        "tags": [topic.lower(), niche, "documentario", "curiosidades", "faceless", "youtube", "brasil"],
        "full_script": full_script,
        "word_count": len(full_script.split()),
        "estimated_duration_minutes": max(1, len(full_script.split()) // 150),
        "niche": niche,
        "style": style,
        "generated_at": datetime.utcnow().isoformat(),
    }


async def generate_narration(script_text: str, voice: str = "pt-BR-AntonioNeural",
                              output_dir: str = "downloads/narrations") -> dict:
    """
    Generate TTS narration from script using edge-tts (free Microsoft voices).
    Returns path to audio file, duration, word count.
    """
    try:
        import edge_tts
    except ImportError:
        logger.error("edge-tts not installed. Install with: pip install edge-tts")
        return {
            "success": False,
            "error": "edge-tts nao instalado. Execute: pip install edge-tts",
            "audio_path": None,
            "duration_seconds": 0,
            "word_count": len(script_text.split()),
        }

    # Ensure output directory exists
    out_path = Path(output_dir)
    out_path.mkdir(parents=True, exist_ok=True)

    # Validate voice
    if voice not in VOICE_OPTIONS:
        voice = "pt-BR-AntonioNeural"

    timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S")
    filename = f"narration_{timestamp}_{uuid.uuid4().hex[:6]}.mp3"
    filepath = out_path / filename
    srt_filename = f"narration_{timestamp}_{uuid.uuid4().hex[:6]}.srt"
    srt_filepath = out_path / srt_filename

    word_count = len(script_text.split())

    try:
        communicate = edge_tts.Communicate(script_text, voice)
        submaker = edge_tts.SubMaker()

        with open(str(filepath), "wb") as audio_file:
            async for chunk in communicate.stream():
                if chunk["type"] == "audio":
                    audio_file.write(chunk["data"])
                elif chunk["type"] == "WordBoundary":
                    submaker.feed(chunk)

        # Save subtitles
        srt_content = submaker.generate_subs()
        if srt_content:
            with open(str(srt_filepath), "w", encoding="utf-8") as srt_file:
                srt_file.write(srt_content)

        # Estimate duration from word count (~150 words/min)
        estimated_duration = (word_count / 150) * 60

        # Try to get actual duration from file size (rough estimate for mp3)
        file_size = filepath.stat().st_size if filepath.exists() else 0
        actual_duration = max(estimated_duration, file_size / 16000)  # rough mp3 bitrate estimate

        return {
            "success": True,
            "audio_path": str(filepath),
            "srt_path": str(srt_filepath) if srt_content else None,
            "filename": filename,
            "voice": voice,
            "voice_info": VOICE_OPTIONS.get(voice, {}),
            "word_count": word_count,
            "duration_seconds": round(actual_duration, 1),
            "duration_formatted": f"{int(actual_duration // 60)}:{int(actual_duration % 60):02d}",
            "file_size_mb": round(file_size / (1024 * 1024), 2),
            "generated_at": datetime.utcnow().isoformat(),
        }

    except Exception as e:
        logger.error(f"TTS generation failed: {e}")
        return {
            "success": False,
            "error": str(e),
            "audio_path": None,
            "word_count": word_count,
            "duration_seconds": 0,
        }


async def select_stock_footage(keywords: list, count: int = 10) -> dict:
    """
    Search for stock footage from Pexels API (free).
    Returns list of video URLs with metadata.
    Falls back to Pixabay if Pexels is not configured.
    """
    import httpx

    pexels_key = os.environ.get("PEXELS_API_KEY", "")
    pixabay_key = os.environ.get("PIXABAY_API_KEY", "")

    videos = []
    source = "none"

    # Try Pexels first
    if pexels_key:
        source = "pexels"
        try:
            async with httpx.AsyncClient(timeout=30) as client:
                for keyword in keywords[:5]:
                    per_page = max(1, count // len(keywords[:5]))
                    r = await client.get(
                        "https://api.pexels.com/videos/search",
                        params={"query": keyword, "per_page": per_page, "orientation": "landscape"},
                        headers={"Authorization": pexels_key},
                    )
                    if r.status_code == 200:
                        data = r.json()
                        for v in data.get("videos", []):
                            # Get best quality video file
                            video_files = v.get("video_files", [])
                            best_file = None
                            for vf in video_files:
                                if vf.get("quality") == "hd" or vf.get("height", 0) >= 720:
                                    best_file = vf
                                    break
                            if not best_file and video_files:
                                best_file = video_files[0]

                            videos.append({
                                "id": v.get("id"),
                                "url": v.get("url"),
                                "video_url": best_file.get("link", "") if best_file else "",
                                "thumbnail": v.get("image", ""),
                                "duration": v.get("duration", 0),
                                "width": best_file.get("width", 0) if best_file else 0,
                                "height": best_file.get("height", 0) if best_file else 0,
                                "keyword": keyword,
                                "source": "pexels",
                                "user": v.get("user", {}).get("name", ""),
                            })
        except Exception as e:
            logger.error(f"Pexels API error: {e}")

    # Try Pixabay as fallback
    if not videos and pixabay_key:
        source = "pixabay"
        try:
            async with httpx.AsyncClient(timeout=30) as client:
                for keyword in keywords[:5]:
                    per_page = max(1, count // len(keywords[:5]))
                    r = await client.get(
                        "https://pixabay.com/api/videos/",
                        params={"key": pixabay_key, "q": keyword, "per_page": per_page},
                    )
                    if r.status_code == 200:
                        data = r.json()
                        for v in data.get("hits", []):
                            video_data = v.get("videos", {})
                            large = video_data.get("large", {})
                            medium = video_data.get("medium", {})
                            best = large if large.get("url") else medium

                            videos.append({
                                "id": v.get("id"),
                                "url": v.get("pageURL", ""),
                                "video_url": best.get("url", ""),
                                "thumbnail": f"https://i.vimeocdn.com/video/{v.get('picture_id', '')}_640x360.jpg",
                                "duration": v.get("duration", 0),
                                "width": best.get("width", 0),
                                "height": best.get("height", 0),
                                "keyword": keyword,
                                "source": "pixabay",
                                "user": v.get("user", ""),
                            })
        except Exception as e:
            logger.error(f"Pixabay API error: {e}")

    # If no API keys, return placeholder suggestions
    if not videos:
        source = "suggestions"
        for i, keyword in enumerate(keywords[:count]):
            videos.append({
                "id": f"suggestion_{i}",
                "url": f"https://www.pexels.com/search/videos/{keyword}/",
                "video_url": "",
                "thumbnail": "",
                "duration": 15,
                "width": 1920,
                "height": 1080,
                "keyword": keyword,
                "source": "suggestion",
                "user": "",
                "note": "Configure PEXELS_API_KEY ou PIXABAY_API_KEY para buscar footage real",
            })

    return {
        "videos": videos[:count],
        "total_found": len(videos),
        "source": source,
        "keywords_used": keywords[:5],
        "api_configured": bool(pexels_key or pixabay_key),
        "fetched_at": datetime.utcnow().isoformat(),
    }


async def generate_thumbnail_prompt(title: str, niche: str) -> dict:
    """
    Generate a thumbnail description/prompt for the video using AI.
    Returns title overlay text, color scheme, composition suggestions.
    """
    from backend.services.local_ai import llm_chat

    niche_styles = {
        "curiosidades": "cores vibrantes, expressao de surpresa, fundo misterioso",
        "historia": "tons sepia, imagens epicas, fonte classica",
        "ciencia": "azul e verde neon, elementos futuristas, graficos",
        "true_crime": "vermelho e preto, sombras dramaticas, tons escuros",
        "tecnologia": "azul eletrico, circuitos, design limpo e moderno",
        "financas": "verde e dourado, graficos subindo, moedas/notas",
        "motivacional": "cores quentes, sol nascendo, silhueta inspiradora",
        "top_listas": "numeros grandes, cores contrastantes, setas",
        "misterios": "roxo e preto, neblina, olho misterioso",
        "saude": "verde e branco, clean, elementos medicos sutis",
    }

    style_hint = niche_styles.get(niche, "cores vibrantes e alto contraste")

    prompt = f"""Crie uma descricao detalhada para thumbnail de YouTube.

TITULO DO VIDEO: {title}
NICHO: {niche}
ESTILO VISUAL DO NICHO: {style_hint}

Retorne em JSON:
{{
    "overlay_text": "Texto curto e impactante para colocar na thumbnail (max 5 palavras)",
    "overlay_text_color": "#FFFFFF",
    "overlay_text_position": "centro ou canto (descreva)",
    "background_description": "Descricao detalhada do fundo da thumbnail",
    "color_scheme": {{
        "primary": "#hex",
        "secondary": "#hex",
        "accent": "#hex"
    }},
    "composition": "Descricao da composicao visual (regra dos tercos, ponto focal, etc)",
    "elements": ["elemento1", "elemento2", "elemento3"],
    "mood": "Atmosfera/sentimento que a thumbnail deve transmitir",
    "ai_image_prompt": "Prompt detalhado em ingles para gerar a thumbnail com IA de imagem (DALL-E/Midjourney style)"
}}

Retorne APENAS o JSON."""

    response = await llm_chat(
        prompt=prompt,
        system="Voce e um designer profissional de thumbnails para YouTube com alto CTR.",
        max_tokens=1024,
        temperature=0.7,
    )

    result = _extract_json_from_response(response)

    if result and "overlay_text" in result:
        result["niche"] = niche
        result["title"] = title
        result["generated_at"] = datetime.utcnow().isoformat()
        return result

    # Fallback
    return {
        "overlay_text": title[:30] + ("..." if len(title) > 30 else ""),
        "overlay_text_color": "#FFFFFF",
        "overlay_text_position": "centro, levemente a esquerda",
        "background_description": f"Fundo dramatico com {style_hint}",
        "color_scheme": {
            "primary": "#7c3aed",
            "secondary": "#1f1538",
            "accent": "#ec4899",
        },
        "composition": "Texto grande centralizado com fundo desfocado, alta saturacao",
        "elements": ["texto em destaque", "borda brilhante", "sombra projetada"],
        "mood": "Curiosidade e urgencia",
        "ai_image_prompt": f"YouTube thumbnail, {niche} channel, dramatic lighting, {title}, high contrast, 16:9 aspect ratio, professional, eye-catching, bold text overlay",
        "niche": niche,
        "title": title,
        "generated_at": datetime.utcnow().isoformat(),
    }


def get_pipeline_status(pipeline_id: str) -> dict:
    """Get current status of a video pipeline."""
    pipe = _pipelines.get(pipeline_id)
    if not pipe:
        return {"error": "Pipeline nao encontrado", "pipeline_id": pipeline_id}

    # Calculate elapsed time
    created = datetime.fromisoformat(pipe["created_at"])
    elapsed = (datetime.utcnow() - created).total_seconds()

    return {
        "id": pipe["id"],
        "topic": pipe["topic"],
        "niche": pipe["niche"],
        "status": pipe["status"],
        "progress": pipe["progress"],
        "current_stage": pipe["current_stage"],
        "stages": pipe["stages"],
        "elapsed_seconds": round(elapsed, 1),
        "elapsed_formatted": f"{int(elapsed // 60)}:{int(elapsed % 60):02d}",
        "created_at": pipe["created_at"],
        "updated_at": pipe["updated_at"],
        "error": pipe.get("error"),
    }


def list_pipelines(limit: int = 20) -> list:
    """List all pipelines with their status."""
    pipes = sorted(
        _pipelines.values(),
        key=lambda p: p.get("created_at", ""),
        reverse=True,
    )[:limit]

    result = []
    for pipe in pipes:
        created = datetime.fromisoformat(pipe["created_at"])
        elapsed = (datetime.utcnow() - created).total_seconds()

        completed_stages = sum(
            1 for s in pipe["stages"].values()
            if s["status"] == "completed"
        )
        total_stages = len(pipe["stages"])

        result.append({
            "id": pipe["id"],
            "topic": pipe["topic"],
            "niche": pipe["niche"],
            "status": pipe["status"],
            "progress": pipe["progress"],
            "current_stage": pipe["current_stage"],
            "completed_stages": f"{completed_stages}/{total_stages}",
            "elapsed_formatted": f"{int(elapsed // 60)}:{int(elapsed % 60):02d}",
            "created_at": pipe["created_at"],
            "error": pipe.get("error"),
        })

    return result


async def batch_produce(db: Session, topics: list, niche: str = "curiosidades",
                         duration_minutes: int = 10) -> dict:
    """
    Queue multiple videos for batch production.
    """
    if not topics:
        return {"error": "Nenhum topico fornecido", "pipelines": []}

    if niche not in DARK_NICHES:
        niche = "curiosidades"

    pipelines = []
    for topic in topics[:10]:  # Limit to 10 at a time
        topic = topic.strip()
        if not topic:
            continue
        result = await generate_video_pipeline(
            db=db,
            topic=topic,
            niche=niche,
            duration_minutes=duration_minutes,
        )
        pipelines.append(result)

    return {
        "batch_id": f"batch_{datetime.utcnow().strftime('%Y%m%d_%H%M%S')}",
        "total_queued": len(pipelines),
        "niche": niche,
        "duration_minutes": duration_minutes,
        "pipelines": pipelines,
        "estimated_total_time_minutes": sum(
            p.get("estimated_time_minutes", 5) for p in pipelines
        ),
        "created_at": datetime.utcnow().isoformat(),
    }


def get_niche_info(niche: str = "") -> dict:
    """Get info about available niches with RPM data."""
    if niche and niche in DARK_NICHES:
        info = DARK_NICHES[niche]
        # Calculate estimated monthly revenue
        videos_per_month = 20
        avg_views = 50000
        monthly_rpm = info["rpm"] * (avg_views / 1000) * videos_per_month

        return {
            "niche": niche,
            **info,
            "estimated_monthly_revenue": round(monthly_rpm, 2),
            "videos_per_month_suggestion": videos_per_month,
            "avg_views_assumption": avg_views,
            "difficulty": _niche_difficulty(niche),
            "competition": _niche_competition(niche),
            "growth_potential": _niche_growth_potential(niche),
            "recommended_topics": _get_recommended_topics(niche),
        }

    # Return all niches
    niches = []
    for name, info in DARK_NICHES.items():
        videos_per_month = 20
        avg_views = 50000
        monthly_rpm = info["rpm"] * (avg_views / 1000) * videos_per_month

        niches.append({
            "niche": name,
            **info,
            "estimated_monthly_revenue": round(monthly_rpm, 2),
            "difficulty": _niche_difficulty(name),
            "competition": _niche_competition(name),
            "growth_potential": _niche_growth_potential(name),
        })

    # Sort by RPM descending
    niches.sort(key=lambda x: x["rpm"], reverse=True)

    return {
        "niches": niches,
        "total": len(niches),
        "note": "RPM e receita estimada baseados em medias do mercado. Valores reais podem variar.",
        "assumptions": {
            "videos_per_month": 20,
            "avg_views_per_video": 50000,
        },
    }


def _niche_difficulty(niche: str) -> str:
    """Rate niche difficulty."""
    hard = {"true_crime", "financas", "historia"}
    medium = {"ciencia", "tecnologia", "saude", "misterios"}
    if niche in hard:
        return "alta"
    if niche in medium:
        return "media"
    return "baixa"


def _niche_competition(niche: str) -> str:
    """Rate niche competition level."""
    high = {"curiosidades", "motivacional", "top_listas"}
    medium = {"tecnologia", "ciencia", "saude"}
    if niche in high:
        return "alta"
    if niche in medium:
        return "media"
    return "baixa"


def _niche_growth_potential(niche: str) -> str:
    """Rate niche growth potential."""
    high = {"financas", "tecnologia", "true_crime", "ciencia"}
    medium = {"historia", "misterios", "saude"}
    if niche in high:
        return "alto"
    if niche in medium:
        return "medio"
    return "moderado"


def _get_recommended_topics(niche: str) -> list:
    """Get recommended topics for a niche."""
    topics_map = {
        "curiosidades": [
            "10 Fatos Surpreendentes Sobre o Corpo Humano",
            "Paises que Proibiram Coisas Absurdas",
            "O que Aconteceria se a Lua Desaparecesse",
            "Lugares Proibidos que Voce Nunca Podera Visitar",
            "Coincidencias Historicas que Parecem Impossiveis",
        ],
        "historia": [
            "A Verdadeira Historia por Tras do Titanic",
            "Civilizacoes Antigas que Desapareceram Misteriosamente",
            "As Maiores Batalhas da Historia que Mudaram o Mundo",
            "Segredos dos Faraos do Egito Antigo",
            "O Dia que Mudou a Historia para Sempre",
        ],
        "ciencia": [
            "O que Existe Alem do Universo Observavel",
            "Como Funciona o Cerebro Humano na Realidade",
            "Paradoxos do Tempo que Cientistas Nao Conseguem Explicar",
            "A Fisica Quantica Explicada de Forma Simples",
            "Descobertas Cientificas Recentes que Mudam Tudo",
        ],
        "true_crime": [
            "Casos Nao Resolvidos que Intrigam Investigadores",
            "O Crime Perfeito que Quase Deu Certo",
            "Golpes Milionarios que Enganaram o Mundo",
            "Fugas de Prisao mais Impressionantes da Historia",
            "Serial Killers que Viviam Vidas Duplas",
        ],
        "tecnologia": [
            "IA em 2026: O que Mudou e o que Vem por Ai",
            "Tecnologias Secretas que os Governos Escondem",
            "Como Hackers Invadem Qualquer Sistema",
            "O Futuro dos Smartphones nos Proximos 10 Anos",
            "Robos que ja Substituem Humanos no Trabalho",
        ],
        "financas": [
            "Como Investir com Pouco Dinheiro e Ter Retorno Real",
            "Erros Financeiros que os Ricos Nunca Cometem",
            "Renda Passiva: 5 Formas que Realmente Funcionam",
            "A Verdade sobre Criptomoedas em 2026",
            "Como Sair das Dividas em 12 Meses",
        ],
        "motivacional": [
            "A Historia de Quem Comecou do Zero e Conquistou Tudo",
            "Habitos que Separam Vencedores de Perdedores",
            "Porque Voce Precisa Falhar para Ter Sucesso",
            "Mentalidade de Milionario: Como Pensar Grande",
            "O Segredo que Ninguem te Conta sobre Disciplina",
        ],
        "top_listas": [
            "Top 10 Lugares mais Perigosos do Mundo",
            "Top 15 Animais mais Mortais que Existem",
            "Top 10 Descobertas Arqueologicas Inexplicaveis",
            "Top 10 Empresas que Quase Faliram e se Reergueram",
            "Top 10 Fenomenos Naturais mais Impressionantes",
        ],
        "misterios": [
            "Misterios do Oceano que Nunca Foram Explicados",
            "O Triangulo das Bermudas: Toda a Verdade",
            "Sinais Alienigenas que a NASA Captou",
            "Profecias Antigas que se Tornaram Realidade",
            "Lugares Assombrados com Evidencias Reais",
        ],
        "saude": [
            "Alimentos que Parecem Saudaveis mas Nao Sao",
            "O que Acontece com seu Corpo Quando Voce Dorme",
            "Habitos Diarios que Destroem sua Saude sem Voce Saber",
            "Jejum Intermitente: Beneficios e Riscos Reais",
            "Sinais de que Seu Corpo Esta Pedindo Ajuda",
        ],
    }
    return topics_map.get(niche, [f"Topico sobre {niche} #{i}" for i in range(1, 6)])


async def generate_seo_metadata(title: str, niche: str, script_summary: str = "") -> dict:
    """
    Generate SEO-optimized title, description, tags for YouTube.
    """
    from backend.services.local_ai import llm_chat

    context = f"\nResumo do conteudo: {script_summary}" if script_summary else ""

    prompt = f"""Gere metadados SEO otimizados para YouTube:

TITULO ORIGINAL: {title}
NICHO: {niche}{context}

Retorne em JSON:
{{
    "seo_title": "Titulo otimizado para SEO (max 100 chars, com keyword principal no inicio)",
    "seo_title_alternatives": ["alternativa1", "alternativa2", "alternativa3"],
    "description": "Descricao completa para YouTube (250-400 palavras). Inclua: resumo do conteudo, timestamps placeholder, keywords naturais, call to action, links placeholder. Use emojis estrategicamente.",
    "tags": ["tag1", "tag2", "tag3", "tag4", "tag5", "tag6", "tag7", "tag8", "tag9", "tag10", "tag11", "tag12", "tag13", "tag14", "tag15"],
    "hashtags": ["#hashtag1", "#hashtag2", "#hashtag3"],
    "category": "Categoria do YouTube (Education, Entertainment, Science & Technology, etc)",
    "primary_keyword": "Keyword principal do video",
    "secondary_keywords": ["keyword2", "keyword3", "keyword4"]
}}

REGRAS:
1. O titulo SEO deve ter a keyword principal no inicio
2. Tags devem misturar long-tail e short-tail keywords
3. Descricao deve ter keywords nos primeiros 150 caracteres
4. Use portugues brasileiro
5. Retorne APENAS o JSON"""

    response = await llm_chat(
        prompt=prompt,
        system="Voce e um especialista em SEO para YouTube com anos de experiencia em otimizacao de videos.",
        max_tokens=2048,
        temperature=0.5,
    )

    result = _extract_json_from_response(response)

    if result and "seo_title" in result:
        result["original_title"] = title
        result["niche"] = niche
        result["generated_at"] = datetime.utcnow().isoformat()
        return result

    # Fallback
    return {
        "seo_title": f"{title} | {niche.capitalize()} - Documentario Completo",
        "seo_title_alternatives": [
            f"{title} - Tudo que Voce Precisa Saber",
            f"A Verdade sobre {title} que Ninguem Conta",
            f"{title} EXPLICADO de Forma Simples",
        ],
        "description": (
            f"{title}\n\n"
            f"Neste video, voce vai descobrir tudo sobre {title}. "
            f"Prepare-se para informacoes que vao mudar sua perspectiva!\n\n"
            f"TIMESTAMPS:\n"
            f"00:00 - Introducao\n"
            f"01:00 - Contexto\n"
            f"03:00 - Desenvolvimento\n"
            f"07:00 - Conclusao\n\n"
            f"Se voce gostou, deixe seu LIKE, INSCREVA-SE e ative o SININHO!\n\n"
            f"#{niche} #{title.split()[0].lower() if title.split() else 'video'} #youtube"
        ),
        "tags": [title.lower(), niche, "documentario", "curiosidades", "faceless",
                 "youtube brasil", "canal dark", "narracao", "fatos", "descobertas",
                 title.split()[0].lower() if title.split() else "video",
                 "2026", "completo", "revelacoes", "impressionante"],
        "hashtags": [f"#{niche}", "#youtube", "#faceless"],
        "category": "Education",
        "primary_keyword": title.lower(),
        "secondary_keywords": [niche, "documentario", "curiosidades"],
        "original_title": title,
        "niche": niche,
        "generated_at": datetime.utcnow().isoformat(),
    }


async def estimate_pipeline_cost(duration_minutes: int = 10, has_narration: bool = True,
                                   footage_clips: int = 10) -> dict:
    """
    Estimate the cost of producing a video with the pipeline.
    All local = nearly free. Only external API costs if any.
    """
    costs = {
        "script_generation": {
            "service": "Ollama (local)",
            "cost_usd": 0.00,
            "note": "LLM local, sem custo de API",
        },
        "narration_tts": {
            "service": "edge-tts (Microsoft, gratuito)",
            "cost_usd": 0.00,
            "note": "TTS gratuito da Microsoft via edge-tts",
            "included": has_narration,
        },
        "stock_footage": {
            "service": "Pexels/Pixabay (gratuito)",
            "cost_usd": 0.00,
            "note": f"{footage_clips} clips de stock footage gratuitos",
            "clips": footage_clips,
        },
        "thumbnail_prompt": {
            "service": "Ollama (local)",
            "cost_usd": 0.00,
            "note": "Geracao de prompt para thumbnail via LLM local",
        },
        "seo_metadata": {
            "service": "Ollama (local)",
            "cost_usd": 0.00,
            "note": "Otimizacao SEO via LLM local",
        },
        "video_editing": {
            "service": "Manual ou FFmpeg (local)",
            "cost_usd": 0.00,
            "note": "Edicao local sem custo de software",
        },
    }

    total_cost = sum(item.get("cost_usd", 0) for item in costs.values())

    # Estimate time
    time_estimate = {
        "script_generation_min": 2,
        "narration_min": max(1, duration_minutes // 3) if has_narration else 0,
        "footage_search_min": 1,
        "thumbnail_min": 1,
        "seo_min": 1,
        "editing_min": duration_minutes * 2,  # Manual editing estimate
        "total_automated_min": 5 + (max(1, duration_minutes // 3) if has_narration else 0),
        "total_with_editing_min": 5 + (max(1, duration_minutes // 3) if has_narration else 0) + duration_minutes * 2,
    }

    # Compare with paid alternatives
    paid_alternatives = {
        "elevenlabs_tts": {
            "cost_usd": round(duration_minutes * 0.30, 2),
            "note": "~$0.30/min para vozes premium",
        },
        "openai_gpt4": {
            "cost_usd": round(0.03 * (duration_minutes * 150 / 750), 2),
            "note": "~$0.03/1K tokens para script",
        },
        "stock_footage_paid": {
            "cost_usd": round(footage_clips * 5.0, 2),
            "note": f"~$5/clip em plataformas pagas ({footage_clips} clips)",
        },
        "total_paid_alternative": 0,
    }
    paid_alternatives["total_paid_alternative"] = round(
        paid_alternatives["elevenlabs_tts"]["cost_usd"] +
        paid_alternatives["openai_gpt4"]["cost_usd"] +
        paid_alternatives["stock_footage_paid"]["cost_usd"],
        2,
    )

    # Revenue estimate
    niche_avg_rpm = sum(n["rpm"] for n in DARK_NICHES.values()) / len(DARK_NICHES)
    estimated_views = 10000  # Conservative estimate for a new channel
    estimated_revenue = round((estimated_views / 1000) * niche_avg_rpm, 2)

    return {
        "duration_minutes": duration_minutes,
        "has_narration": has_narration,
        "footage_clips": footage_clips,
        "costs": costs,
        "total_cost_usd": total_cost,
        "total_cost_brl": round(total_cost * 5.0, 2),
        "time_estimate": time_estimate,
        "paid_alternatives": paid_alternatives,
        "savings_usd": paid_alternatives["total_paid_alternative"],
        "revenue_estimate": {
            "avg_rpm": round(niche_avg_rpm, 2),
            "estimated_views": estimated_views,
            "estimated_revenue_usd": estimated_revenue,
            "note": "Estimativa conservadora para canal novo. Canais estabelecidos podem ter 10-100x mais views.",
        },
        "roi_note": "Custo ZERO com pipeline local. Todo lucro e 100% margem.",
    }


def get_production_stats() -> dict:
    """Get overall production statistics."""
    total = len(_pipelines)
    completed = sum(1 for p in _pipelines.values() if p["status"] == "completed")
    failed = sum(1 for p in _pipelines.values() if p["status"] == "failed")
    running = sum(1 for p in _pipelines.values() if p["status"] == "started")

    # Niche distribution
    niche_counts: dict = {}
    for p in _pipelines.values():
        n = p.get("niche", "unknown")
        niche_counts[n] = niche_counts.get(n, 0) + 1

    # Average pipeline time for completed
    avg_time = 0
    completed_times = []
    for p in _pipelines.values():
        if p["status"] == "completed":
            try:
                created = datetime.fromisoformat(p["created_at"])
                updated = datetime.fromisoformat(p["updated_at"])
                elapsed = (updated - created).total_seconds()
                completed_times.append(elapsed)
            except (ValueError, KeyError):
                pass

    if completed_times:
        avg_time = sum(completed_times) / len(completed_times)

    # Stage success rates
    stage_stats: dict = {}
    for p in _pipelines.values():
        for stage_name, stage_data in p.get("stages", {}).items():
            if stage_name not in stage_stats:
                stage_stats[stage_name] = {"total": 0, "completed": 0, "failed": 0}
            stage_stats[stage_name]["total"] += 1
            if stage_data["status"] == "completed":
                stage_stats[stage_name]["completed"] += 1
            elif stage_data["status"] == "failed":
                stage_stats[stage_name]["failed"] += 1

    # Estimate total content produced
    total_minutes = sum(
        p.get("duration_minutes", 10) for p in _pipelines.values()
        if p["status"] == "completed"
    )

    # Revenue estimates
    total_estimated_revenue = 0
    for p in _pipelines.values():
        if p["status"] == "completed":
            niche = p.get("niche", "curiosidades")
            rpm = DARK_NICHES.get(niche, {}).get("rpm", 4.0)
            # Conservative: 10k views per video
            total_estimated_revenue += (10000 / 1000) * rpm

    return {
        "total_pipelines": total,
        "completed": completed,
        "failed": failed,
        "running": running,
        "pending": total - completed - failed - running,
        "success_rate": round((completed / total * 100) if total > 0 else 0, 1),
        "niche_distribution": niche_counts,
        "avg_pipeline_time_seconds": round(avg_time, 1),
        "avg_pipeline_time_formatted": f"{int(avg_time // 60)}:{int(avg_time % 60):02d}" if avg_time > 0 else "N/A",
        "stage_stats": stage_stats,
        "total_content_minutes": total_minutes,
        "total_content_formatted": f"{total_minutes // 60}h {total_minutes % 60}min",
        "estimated_total_revenue_usd": round(total_estimated_revenue, 2),
        "estimated_total_revenue_brl": round(total_estimated_revenue * 5.0, 2),
        "cost_total_usd": 0.00,
        "profit_margin": "100%",
        "available_niches": len(DARK_NICHES),
        "available_voices": len(VOICE_OPTIONS),
    }
