import os
import logging
import httpx
import asyncio
from telegram import Update
from telegram.ext import ApplicationBuilder, ContextTypes, MessageHandler, filters
from dotenv import load_dotenv

# Carrega as variáveis do arquivo .env
load_dotenv()

# Configurações obtidas do .env
TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
ALLOWED_USER_ID = os.getenv("TELEGRAM_CHAT_ID")
# Sincroniza com a PORTA definida no .env (Dica: .env diz 8000)
API_PORT = os.getenv("PORT", "8001")
API_BASE_URL = f"http://localhost:{API_PORT}"

# O ID permitido deve ser comparado como string ou int, padronizando aqui
if ALLOWED_USER_ID:
    ALLOWED_USER_ID = int(ALLOWED_USER_ID)

# Configuração de Logs
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)
logger = logging.getLogger(__name__)

# Dicionário global para manter o histórico (Em um sistema de produção, usar Redis ou DB)
chat_histories = {}

async def call_antigravity_api(endpoint: str, payload: dict) -> str:
    """Faz a chamada para a API interna do BotVPS."""
    async with httpx.AsyncClient(timeout=120.0) as client:
        try:
            logger.info(f"Enviando payload para {endpoint}: {payload.get('text', payload.get('task'))}")
            response = await client.post(f"{API_BASE_URL}{endpoint}", json=payload)
            response.raise_for_status()
            data = response.json()
            
            # Tenta extrair a resposta de diferentes formatos possíveis
            reply = data.get("reply") or data.get("message") or str(data)
            return reply
        except Exception as e:
            logger.error(f"Erro ao chamar API Antigravity: {str(e)}")
            return f"❌ *Erro na API:* {str(e)}"

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Manipulador central de mensagens."""
    if not update.message or not update.message.text:
        return

    chat_id = update.effective_chat.id
    user_id = update.effective_user.id
    
    # Filtro de Segurança
    if ALLOWED_USER_ID and user_id != ALLOWED_USER_ID:
        logger.warning(f"Acesso negado para o ID: {user_id}. Esperado: {ALLOWED_USER_ID}")
        return

    text = update.message.text
    logger.info(f"Mensagem recebida de {user_id}: {text}")

    # Inicializa histórico se não existir
    if chat_id not in chat_histories:
        chat_histories[chat_id] = []

    # Diferenciação entre comandos de sistema e conhecimento geral
    if text.startswith(('/bash', '/vps', '/cmd')):
        # Comandos de sistema geralmente não precisam de histórico de chat natural
        task = text.replace('/bash', '').replace('/vps', '').replace('/cmd', '').strip()
        
        if not task:
            await update.message.reply_text("❓ Por favor, envie o comando após o prefixo.")
            return

        await update.message.reply_text("⚙️ *Processando tarefa no Claw System...*", parse_mode='Markdown')
        reply = await call_antigravity_api("/api/orchestrate", {"task": task})
    else:
        # Chat Natural com contexto
        await context.bot.send_chat_action(chat_id=chat_id, action="typing")
        
        # Prepara payload com histórico
        payload = {
            "text": text,
            "history": chat_histories[chat_id][-10:] # Envia os últimos 10 turnos
        }
        
        reply = await call_antigravity_api("/api/chat", payload)
        
        # Atualiza histórico Local
        chat_histories[chat_id].append({"user": text, "bot": reply})
        # Mantém apenas os últimos 15 para não crescer infinito no middleware
        if len(chat_histories[chat_id]) > 15:
            chat_histories[chat_id].pop(0)

    # Envia a resposta de volta para o usuário
    if len(reply) > 4000:
        reply = reply[:3900] + "... [Texto truncado]"
    
    try:
        await update.message.reply_text(reply, parse_mode='Markdown')
    except Exception as e:
        logger.error(f"Erro ao enviar Markdown: {e}. Tentando texto puro.")
        await update.message.reply_text(reply)

async def handle_voice(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Manipula mensagens de voz do Telegram."""
    if not update.message or not update.message.voice:
        return

    chat_id = update.effective_chat.id
    user_id = update.effective_user.id
    
    # Filtro de Segurança
    if ALLOWED_USER_ID and user_id != ALLOWED_USER_ID:
        return

    await context.bot.send_chat_action(chat_id=chat_id, action="record_voice")
    
    # 1. Download do áudio do Telegram
    voice_file = await update.message.voice.get_file()
    temp_path = f"/tmp/tg_voice_{uuid.uuid4().hex}.ogg"
    await voice_file.download_to_drive(temp_path)
    
    logger.info(f"Voz recebida de {user_id}. Enviando para API de Áudio...")

    # 2. Envia para a API interna de áudio
    # Como o bridge e API estão na mesma máquina, compartilhamos o /tmp se necessário
    # Mas vamos usar multipart para ser fiel à API
    async with httpx.AsyncClient(timeout=120.0) as client:
        try:
            with open(temp_path, "rb") as f:
                # O parâmetro history pode ser adicionado futuramente similar ao chat
                files = {"audio": (os.path.basename(temp_path), f, "audio/ogg")}
                response = await client.post(f"{API_BASE_URL}/api/chat-audio", files=files)
                response.raise_for_status()
                data = response.json()
                
                user_text = data.get("text", "[Voz não transcrita]")
                bot_reply = data.get("reply", "Erro no processamento.")
                audio_url = data.get("audio_url") # Ex: /api/audio/file.mp3

                # Envia transcrição do usuário (sem markdown no conteúdo para evitar bugs)
                await update.message.reply_text(f"🎤 *Sua mensagem:* {user_text}")
                
                # Envia resposta em texto com fallback se o Markdown falhar
                try:
                    await update.message.reply_text(bot_reply, parse_mode='Markdown')
                except Exception as e:
                    logger.error(f"Erro Markdown na voz: {e}")
                    await update.message.reply_text(bot_reply)

                # 3. Envia resposta em áudio (TTS)
                if audio_url:
                    filename = audio_url.split("/")[-1]
                    audio_path = os.path.join("/tmp", filename)
                    if os.path.exists(audio_path):
                        with open(audio_path, "rb") as audio_file:
                            await context.bot.send_voice(chat_id=chat_id, voice=audio_file)
                
                # Atualiza histórico local
                if chat_id not in chat_histories: chat_histories[chat_id] = []
                chat_histories[chat_id].append({"user": user_text, "bot": bot_reply})

        except Exception as e:
            logger.error(f"Erro ao processar áudio: {str(e)}")
            await update.message.reply_text(f"❌ *Erro no áudio:* {str(e)}")
        finally:
            if os.path.exists(temp_path): os.remove(temp_path)

if __name__ == '__main__':
    if not TOKEN:
        logger.error("ERRO: TELEGRAM_BOT_TOKEN não encontrado no .env!")
        exit(1)

    # Inicializa o Bot (python-telegram-bot v20+)
    application = ApplicationBuilder().token(TOKEN).build()
    
    # Adiciona o handler para mensagens de texto
    text_handler = MessageHandler(filters.TEXT | filters.COMMAND, handle_message)
    application.add_handler(text_handler)
    
    # Adiciona o handler para mensagens de VOZ
    import uuid
    voice_handler = MessageHandler(filters.VOICE, handle_voice)
    application.add_handler(voice_handler)
    
    logger.info("Bot Ponte Antigravity (Middleware - Texto & Voz) iniciado...")
    application.run_polling()
