#!/usr/bin/env python3
"""
Audio Transcriber v1.1.0
Transcreve áudio para texto e gera atas/resumos usando LLM.
"""

import os
import sys
import json
import subprocess
import shutil
from datetime import datetime
from pathlib import Path

# Rich for beautiful terminal output
try:
    from rich.console import Console
    from rich.prompt import Prompt
    from rich.panel import Panel
    from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn
    from rich import print as rprint
    RICH_AVAILABLE = True
except ImportError:
    RICH_AVAILABLE = False
    print("⚠️  Installing rich for better UI...")
    subprocess.run([sys.executable, "-m", "pip", "install", "--user", "rich"], check=False)
    from rich.console import Console
    from rich.prompt import Prompt
    from rich.panel import Panel
    from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn
    from rich import print as rprint

# tqdm for progress bars
try:
    from tqdm import tqdm
except ImportError:
    print("⚠️  Installing tqdm for progress bars...")
    subprocess.run([sys.executable, "-m", "pip", "install", "--user", "tqdm"], check=False)
    from tqdm import tqdm

# Whisper engines
try:
    from faster_whisper import WhisperModel
    TRANSCRIBER = "faster-whisper"
except ImportError:
    try:
        import whisper
        TRANSCRIBER = "whisper"
    except ImportError:
        print("❌ Nenhum engine de transcrição encontrado!")
        print("   Instale: pip install faster-whisper")
        sys.exit(1)

console = Console()

# Template padrão RISEN para fallback
DEFAULT_MEETING_PROMPT = """
Role: Você é um transcritor profissional especializado em documentação.

Instructions: Transforme a transcrição fornecida em um documento estruturado e profissional.

Steps:
1. Identifique o tipo de conteúdo (reunião, palestra, entrevista, etc.)
2. Extraia os principais tópicos e pontos-chave
3. Identifique participantes/speakers (se aplicável)
4. Extraia decisões tomadas e ações definidas (se reunião)
5. Organize em formato apropriado com seções claras
6. Use Markdown para formatação profissional

End Goal: Documento final bem estruturado, legível e pronto para distribuição.

Narrowing: 
- Mantenha objetividade e clareza
- Preserve contexto importante
- Use formatação Markdown adequada
- Inclua timestamps relevantes quando aplicável
"""


def detect_cli_tool():
    """Detecta qual CLI de LLM está disponível (claude > gh copilot)."""
    if shutil.which('claude'):
        return 'claude'
    elif shutil.which('gh'):
        result = subprocess.run(['gh', 'copilot', '--version'], 
                                capture_output=True, text=True)
        if result.returncode == 0:
            return 'gh-copilot'
    return None


def invoke_prompt_engineer(raw_prompt, timeout=90):
    """
    Invoca prompt-engineer skill via CLI para melhorar/gerar prompts.
    
    Args:
        raw_prompt: Prompt a ser melhorado ou meta-prompt
        timeout: Timeout em segundos
    
    Returns:
        str: Prompt melhorado ou DEFAULT_MEETING_PROMPT se falhar
    """
    try:
        # Tentar via gh copilot
        console.print("[dim]   Invocando prompt-engineer...[/dim]")
        
        result = subprocess.run(
            ['gh', 'copilot', 'suggest', '-t', 'shell', raw_prompt],
            capture_output=True,
            text=True,
            timeout=timeout
        )
        
        if result.returncode == 0 and result.stdout.strip():
            return result.stdout.strip()
        else:
            console.print("[yellow]⚠️  prompt-engineer não respondeu, usando template padrão[/yellow]")
            return DEFAULT_MEETING_PROMPT
            
    except subprocess.TimeoutExpired:
        console.print(f"[red]⚠️  Timeout após {timeout}s, usando template padrão[/red]")
        return DEFAULT_MEETING_PROMPT
    except Exception as e:
        console.print(f"[red]⚠️  Erro ao invocar prompt-engineer: {e}[/red]")
        return DEFAULT_MEETING_PROMPT


def handle_prompt_workflow(user_prompt, transcript):
    """
    Gerencia fluxo completo de prompts com prompt-engineer.
    
    Cenário A: Usuário forneceu prompt → Melhorar AUTOMATICAMENTE → Confirmar
    Cenário B: Sem prompt → Sugerir tipo → Confirmar → Gerar → Confirmar
    
    Returns:
        str: Prompt final a usar, ou None se usuário recusou processamento
    """
    prompt_engineer_available = os.path.exists(
        os.path.expanduser('~/.copilot/skills/prompt-engineer/SKILL.md')
    )
    
    # ========== CENÁRIO A: USUÁRIO FORNECEU PROMPT ==========
    if user_prompt:
        console.print("\n[cyan]📝 Prompt fornecido pelo usuário[/cyan]")
        console.print(Panel(user_prompt[:300] + ("..." if len(user_prompt) > 300 else ""), 
                           title="Prompt original", border_style="dim"))
        
        if prompt_engineer_available:
            # Melhora AUTOMATICAMENTE (sem perguntar)
            console.print("\n[cyan]🔧 Melhorando prompt com prompt-engineer...[/cyan]")
            
            improved_prompt = invoke_prompt_engineer(
                f"melhore este prompt:\n\n{user_prompt}"
            )
            
            # Mostrar AMBAS versões
            console.print("\n[green]✨ Versão melhorada:[/green]")
            console.print(Panel(improved_prompt[:500] + ("..." if len(improved_prompt) > 500 else ""), 
                               title="Prompt otimizado", border_style="green"))
            
            console.print("\n[dim]📝 Versão original:[/dim]")
            console.print(Panel(user_prompt[:300] + ("..." if len(user_prompt) > 300 else ""), 
                               title="Seu prompt", border_style="dim"))
            
            # Pergunta qual usar
            confirm = Prompt.ask(
                "\n💡 Usar versão melhorada?",
                choices=["s", "n"],
                default="s"
            )
            
            return improved_prompt if confirm == "s" else user_prompt
        else:
            # prompt-engineer não disponível
            console.print("[yellow]⚠️  prompt-engineer skill não disponível[/yellow]")
            console.print("[dim]✅ Usando seu prompt original[/dim]")
            return user_prompt
    
    # ========== CENÁRIO B: SEM PROMPT - AUTO-GERAÇÃO ==========
    else:
        console.print("\n[yellow]⚠️  Nenhum prompt fornecido.[/yellow]")
        
        if not prompt_engineer_available:
            console.print("[yellow]⚠️  prompt-engineer skill não encontrado[/yellow]")
            console.print("[dim]Usando template padrão...[/dim]")
            return DEFAULT_MEETING_PROMPT
        
        # PASSO 1: Perguntar se quer auto-gerar
        console.print("Posso analisar o transcript e sugerir um formato de resumo/ata?")
        
        generate = Prompt.ask(
            "\n💡 Gerar prompt automaticamente?",
            choices=["s", "n"],
            default="s"
        )
        
        if generate == "n":
            console.print("[dim]✅ Ok, gerando apenas transcript.md (sem ata)[/dim]")
            return None  # Sinaliza: não processar com LLM
        
        # PASSO 2: Analisar transcript e SUGERIR tipo
        console.print("\n[cyan]🔍 Analisando transcript...[/cyan]")
        
        suggestion_meta_prompt = f"""
Analise este transcript ({len(transcript)} caracteres) e sugira:

1. Tipo de conteúdo (reunião, palestra, entrevista, etc.)
2. Formato de saída recomendado (ata formal, resumo executivo, notas estruturadas)
3. Framework ideal (RISEN, RODES, STAR, etc.)

Primeiras 1000 palavras do transcript:
{transcript[:4000]}

Responda em 2-3 linhas concisas.
"""
        
        suggested_type = invoke_prompt_engineer(suggestion_meta_prompt)
        
        # PASSO 3: Mostrar sugestão e CONFIRMAR
        console.print("\n[green]💡 Sugestão de formato:[/green]")
        console.print(Panel(suggested_type, title="Análise do transcript", border_style="green"))
        
        confirm_type = Prompt.ask(
            "\n💡 Usar este formato?",
            choices=["s", "n"],
            default="s"
        )
        
        if confirm_type == "n":
            console.print("[dim]Usando template padrão...[/dim]")
            return DEFAULT_MEETING_PROMPT
        
        # PASSO 4: Gerar prompt completo baseado na sugestão
        console.print("\n[cyan]✨ Gerando prompt estruturado...[/cyan]")
        
        final_meta_prompt = f"""
Crie um prompt completo e estruturado (usando framework apropriado) para:

{suggested_type}

O prompt deve instruir uma IA a transformar o transcript em um documento
profissional e bem formatado em Markdown.
"""
        
        generated_prompt = invoke_prompt_engineer(final_meta_prompt)
        
        # PASSO 5: Mostrar prompt gerado e CONFIRMAR
        console.print("\n[green]✅ Prompt gerado:[/green]")
        console.print(Panel(generated_prompt[:600] + ("..." if len(generated_prompt) > 600 else ""), 
                           title="Preview", border_style="green"))
        
        confirm_final = Prompt.ask(
            "\n💡 Usar este prompt?",
            choices=["s", "n"],
            default="s"
        )
        
        if confirm_final == "s":
            return generated_prompt
        else:
            console.print("[dim]Usando template padrão...[/dim]")
            return DEFAULT_MEETING_PROMPT


def process_with_llm(transcript, prompt, cli_tool='claude', timeout=300):
    """
    Processa transcript com LLM usando prompt fornecido.
    
    Args:
        transcript: Texto transcrito
        prompt: Prompt instruindo como processar
        cli_tool: 'claude' ou 'gh-copilot'
        timeout: Timeout em segundos
    
    Returns:
        str: Ata/resumo processado
    """
    full_prompt = f"{prompt}\n\n---\n\nTranscrição:\n\n{transcript}"
    
    try:
        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            transient=True
        ) as progress:
            progress.add_task(description=f"🤖 Processando com {cli_tool}...", total=None)
            
            if cli_tool == 'claude':
                result = subprocess.run(
                    ['claude', '-'],
                    input=full_prompt,
                    capture_output=True,
                    text=True,
                    timeout=timeout
                )
            elif cli_tool == 'gh-copilot':
                result = subprocess.run(
                    ['gh', 'copilot', 'suggest', '-t', 'shell', full_prompt],
                    capture_output=True,
                    text=True,
                    timeout=timeout
                )
            else:
                raise ValueError(f"CLI tool desconhecido: {cli_tool}")
        
        if result.returncode == 0:
            return result.stdout.strip()
        else:
            console.print(f"[red]❌ Erro ao processar com {cli_tool}[/red]")
            console.print(f"[dim]{result.stderr[:200]}[/dim]")
            return None
            
    except subprocess.TimeoutExpired:
        console.print(f"[red]❌ Timeout após {timeout}s[/red]")
        return None
    except Exception as e:
        console.print(f"[red]❌ Erro: {e}[/red]")
        return None


def transcribe_audio(audio_file, model="base"):
    """
    Transcreve áudio usando Whisper com barra de progresso.
    
    Returns:
        dict: {language, duration, segments: [{start, end, text}]}
    """
    console.print(f"\n[cyan]🎙️  Transcrevendo áudio com {TRANSCRIBER}...[/cyan]")
    
    try:
        if TRANSCRIBER == "faster-whisper":
            model_obj = WhisperModel(model, device="cpu", compute_type="int8")
            segments, info = model_obj.transcribe(
                audio_file,
                language=None,
                vad_filter=True,
                word_timestamps=True
            )
            
            data = {
                "language": info.language,
                "language_probability": round(info.language_probability, 2),
                "duration": info.duration,
                "segments": []
            }
            
            # Converter generator em lista com progresso
            console.print("[dim]Processando segmentos...[/dim]")
            for segment in tqdm(segments, desc="Segmentos", unit="seg"):
                data["segments"].append({
                    "start": round(segment.start, 2),
                    "end": round(segment.end, 2),
                    "text": segment.text.strip()
                })
        
        else:  # whisper original
            import whisper
            model_obj = whisper.load_model(model)
            result = model_obj.transcribe(audio_file, word_timestamps=True)
            
            data = {
                "language": result["language"],
                "duration": result["segments"][-1]["end"] if result["segments"] else 0,
                "segments": result["segments"]
            }
        
        console.print(f"[green]✅ Transcrição completa! Idioma: {data['language'].upper()}[/green]")
        console.print(f"[dim]   {len(data['segments'])} segmentos processados[/dim]")
        
        return data
        
    except Exception as e:
        console.print(f"[red]❌ Erro na transcrição: {e}[/red]")
        sys.exit(1)


def save_outputs(transcript_text, ata_text, audio_file, output_dir="."):
    """
    Salva transcript e ata em arquivos .md com timestamp.
    
    Returns:
        tuple: (transcript_path, ata_path or None)
    """
    timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
    base_name = Path(audio_file).stem
    
    # Sempre salva transcript
    transcript_filename = f"transcript-{timestamp}.md"
    transcript_path = Path(output_dir) / transcript_filename
    
    with open(transcript_path, 'w', encoding='utf-8') as f:
        f.write(transcript_text)
    
    console.print(f"[green]✅ Transcript salvo:[/green] {transcript_filename}")
    
    # Salva ata se existir
    ata_path = None
    if ata_text:
        ata_filename = f"ata-{timestamp}.md"
        ata_path = Path(output_dir) / ata_filename
        
        with open(ata_path, 'w', encoding='utf-8') as f:
            f.write(ata_text)
        
        console.print(f"[green]✅ Ata salva:[/green] {ata_filename}")
    
    return str(transcript_path), str(ata_path) if ata_path else None


def main():
    """Função principal."""
    import argparse
    
    parser = argparse.ArgumentParser(description="Audio Transcriber v1.1.0")
    parser.add_argument("audio_file", help="Arquivo de áudio para transcrever")
    parser.add_argument("--prompt", help="Prompt customizado para processar transcript")
    parser.add_argument("--model", default="base", help="Modelo Whisper (tiny/base/small/medium/large)")
    parser.add_argument("--output-dir", default=".", help="Diretório de saída")
    
    args = parser.parse_args()
    
    # Verificar arquivo existe
    if not os.path.exists(args.audio_file):
        console.print(f"[red]❌ Arquivo não encontrado: {args.audio_file}[/red]")
        sys.exit(1)
    
    console.print("[bold cyan]🎵 Audio Transcriber v1.1.0[/bold cyan]\n")
    
    # Step 1: Transcrever
    transcription_data = transcribe_audio(args.audio_file, model=args.model)
    
    # Gerar texto do transcript
    transcript_text = f"# Transcrição de Áudio\n\n"
    transcript_text += f"**Arquivo:** {Path(args.audio_file).name}\n"
    transcript_text += f"**Idioma:** {transcription_data['language'].upper()}\n"
    transcript_text += f"**Data:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
    transcript_text += "---\n\n## Transcrição Completa\n\n"
    
    for seg in transcription_data["segments"]:
        start_min = int(seg["start"] // 60)
        start_sec = int(seg["start"] % 60)
        end_min = int(seg["end"] // 60)
        end_sec = int(seg["end"] % 60)
        transcript_text += f"**[{start_min:02d}:{start_sec:02d} → {end_min:02d}:{end_sec:02d}]**  \n{seg['text']}\n\n"
    
    # Step 2: Detectar CLI
    cli_tool = detect_cli_tool()
    
    if not cli_tool:
        console.print("\n[yellow]⚠️  Nenhuma CLI de IA detectada (Claude ou GitHub Copilot)[/yellow]")
        console.print("[dim]ℹ️  Salvando apenas transcript.md...[/dim]")
        
        save_outputs(transcript_text, None, args.audio_file, args.output_dir)

        console.print("\n[cyan]💡 Para gerar ata/resumo:[/cyan]")
        console.print("  - Instale Claude CLI: pip install claude-cli")
        console.print("  - Ou GitHub Copilot CLI já está instalado (gh copilot)")
        return
    
    console.print(f"\n[green]✅ CLI detectada: {cli_tool}[/green]")
    
    # Step 3: Workflow de prompt
    final_prompt = handle_prompt_workflow(args.prompt, transcript_text)
    
    if final_prompt is None:
        # Usuário recusou processamento
        save_outputs(transcript_text, None, args.audio_file, args.output_dir)
        return
    
    # Step 4: Processar com LLM
    ata_text = process_with_llm(transcript_text, final_prompt, cli_tool)
    
    if ata_text:
        console.print("[green]✅ Ata gerada com sucesso![/green]")
    else:
        console.print("[yellow]⚠️  Falha ao gerar ata, salvando apenas transcript[/yellow]")
    
    # Step 5: Salvar arquivos
    console.print("\n[cyan]💾 Salvando arquivos...[/cyan]")
    save_outputs(transcript_text, ata_text, args.audio_file, args.output_dir)

    console.print("\n[bold green]✅ Concluído![/bold green]")


if __name__ == "__main__":
    main()
