#!/usr/bin/env python3
"""
Test integrazione Telegram REALE – Canale configurato
======================================================

Testa:
1. Lettura canale Telegram dal database (bot_token + chat_id)
2. Chiamata diretta alla funzione send_message (httpx → Bot API)
3. Verifica risposta Telegram (message_id, chat, testo)
4. Test via NotificationService.test_channel (flusso completo)

Eseguire DENTRO il container backend:
  docker exec pechub-backend-1 python \
    /app/tests/integration/test_telegram_real.py

Oppure specificando credenziali manuali via env:
  docker exec -e TELEGRAM_BOT_TOKEN=xxx -e TELEGRAM_CHAT_ID=-100yyy \
    pechub-backend-1 python /app/tests/integration/test_telegram_real.py
"""

import asyncio
import base64
import json
import os
import sys
from datetime import datetime

# ─── Variabili d'ambiente ─────────────────────────────────────────────────────
os.environ.setdefault("ENCRYPTION_KEY", "6465762d656e6372797074696f6e2d6b65792d6e6f742d666f722d70726f6400")
os.environ.setdefault("SECRET_KEY", "dev-secret-key-not-for-production-use-only-for-local-0000000000000")
os.environ.setdefault("DATABASE_URL", "postgresql+asyncpg://pechub:pechub_dev_password@db:5432/pechub")
os.environ.setdefault("REDIS_URL", "redis://redis:6379/0")
os.environ.setdefault("MINIO_ENDPOINT", "minio:9000")


# ─── Utilities ────────────────────────────────────────────────────────────────

def _sep(char: str = "─", width: int = 60) -> None:
    print(char * width)


def _banner(bot_token_masked: str, chat_id: str) -> None:
    _sep("═")
    print("  PEChub – Test Telegram Reale")
    _sep("═")
    print(f"  Timestamp  : {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print(f"  Bot Token  : {bot_token_masked}")
    print(f"  Chat ID    : {chat_id}")
    _sep("═")
    print()


def _mask_token(token: str) -> str:
    """Nasconde la parte centrale del token per sicurezza."""
    parts = token.split(":")
    if len(parts) == 2:
        return f"{parts[0]}:{'*' * 10}...{parts[1][-6:]}"
    return token[:8] + "..." + token[-6:]


def _decrypt_b64(enc: str) -> dict:
    """Decifra il config_enc (base64 semplice come in notification_service.py)."""
    raw = base64.b64decode(enc.encode())
    return json.loads(raw.decode())


# ─── STEP 1: Lettura canale dal DB ───────────────────────────────────────────

async def load_channel_from_db() -> tuple[str, str, str] | None:
    """
    Carica bot_token e chat_id dal primo canale Telegram nel DB.
    Restituisce (channel_id, bot_token, chat_id) o None se non trovato.
    """
    _sep()
    print("STEP 1 – LETTURA CANALE TELEGRAM DAL DATABASE")
    _sep()

    try:
        from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
        from sqlalchemy import text

        db_url = os.environ["DATABASE_URL"]
        engine = create_async_engine(db_url)
        async with AsyncSession(engine) as session:
            result = await session.execute(
                text(
                    "SELECT id, name, config, config_enc "
                    "FROM notification_channels "
                    "WHERE channel_type = 'telegram' AND is_active = true "
                    "ORDER BY created_at DESC LIMIT 1"
                )
            )
            row = result.fetchone()

        if not row:
            print("  ⚠️  Nessun canale Telegram attivo trovato nel database.")
            print("     Crea un canale Telegram tramite l'interfaccia o via API.")
            return None

        channel_id = str(row[0])
        channel_name = row[1]
        config = row[2] or {}
        config_enc = row[3]

        chat_id = str(config.get("chat_id", ""))
        if not chat_id:
            print(f"  ❌ Il canale '{channel_name}' non ha chat_id configurato.")
            return None

        if not config_enc:
            print(f"  ❌ Il canale '{channel_name}' non ha bot_token configurato (config_enc mancante).")
            return None

        secret = _decrypt_b64(config_enc)
        bot_token = secret.get("bot_token", "")
        if not bot_token:
            print(f"  ❌ Il canale '{channel_name}' non ha bot_token nel config_enc.")
            return None

        print(f"  ✅ Canale trovato: '{channel_name}'")
        print(f"     ID          : {channel_id}")
        print(f"     Chat ID     : {chat_id}")
        print(f"     Bot Token   : {_mask_token(bot_token)}")
        print()
        return channel_id, bot_token, chat_id

    except Exception as exc:
        print(f"  ❌ Errore lettura DB: {exc}")
        import traceback
        traceback.print_exc()
        return None


# ─── STEP 2: Invio diretto via httpx ─────────────────────────────────────────

async def test_direct_send(bot_token: str, chat_id: str) -> bool:
    """
    Testa send_message() direttamente (senza passare da DB/service).
    """
    _sep()
    print("STEP 2 – INVIO DIRETTO VIA BOT API (httpx)")
    _sep()

    from app.notifications.telegram import TelegramError, send_message

    ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    text = (
        f"🧪 <b>PEChub – Test integrazione</b>\n\n"
        f"Test invio diretto via <code>send_message()</code>\n\n"
        f"🕐 <i>{ts}</i>"
    )

    print(f"  Chiamata: send_message(chat_id={chat_id}, parse_mode=HTML)")
    print()

    try:
        result = await send_message(
            bot_token=bot_token,
            chat_id=chat_id,
            text=text,
            parse_mode="HTML",
        )
        msg_id = result.get("message_id")
        chat_info = result.get("chat", {})
        chat_title = chat_info.get("title") or chat_info.get("username") or chat_info.get("id")
        date = result.get("date")

        print(f"  ✅ INVIO OK")
        print(f"     message_id : {msg_id}")
        print(f"     chat       : {chat_title}")
        print(f"     date       : {date}")
        print()
        return True

    except TelegramError as exc:
        print(f"  ❌ TelegramError: {exc}")
        if exc.http_status:
            print(f"     HTTP status: {exc.http_status}")
        if exc.api_code:
            print(f"     API code   : {exc.api_code}")
        print()
        return False

    except Exception as exc:
        print(f"  ❌ Errore imprevisto: {exc}")
        import traceback
        traceback.print_exc()
        print()
        return False


# ─── STEP 3: Test via send_test_message ──────────────────────────────────────

async def test_send_test_message(bot_token: str, chat_id: str) -> bool:
    """
    Testa send_test_message() che invia il messaggio formattato standard.
    """
    _sep()
    print("STEP 3 – INVIO MESSAGGIO DI TEST FORMATTATO")
    _sep()

    from app.notifications.telegram import TelegramError, send_test_message

    print("  Chiamata: send_test_message(channel_name='Test PEChub')")
    print()

    try:
        result = await send_test_message(
            bot_token=bot_token,
            chat_id=chat_id,
            channel_name="Test PEChub",
        )
        msg_id = result.get("message_id")
        print(f"  ✅ INVIO OK – message_id={msg_id}")
        print()
        return True

    except TelegramError as exc:
        print(f"  ❌ TelegramError: {exc}")
        print()
        return False


# ─── STEP 4: Test via NotificationService ────────────────────────────────────

async def test_via_notification_service(channel_id: str) -> bool:
    """
    Testa il flusso completo: NotificationService.test_channel()
    che carica dal DB, decifra il token e chiama la Bot API.
    """
    _sep()
    print("STEP 4 – FLUSSO COMPLETO VIA NotificationService.test_channel()")
    _sep()

    import uuid
    from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
    from sqlalchemy import text

    # Recupera il tenant_id del canale
    db_url = os.environ["DATABASE_URL"]
    engine = create_async_engine(db_url)

    try:
        async with AsyncSession(engine) as session:
            r = await session.execute(
                text("SELECT tenant_id FROM notification_channels WHERE id = :id"),
                {"id": channel_id},
            )
            row = r.fetchone()
            if not row:
                print(f"  ❌ Canale {channel_id} non trovato nel DB.")
                return False
            tenant_id = uuid.UUID(str(row[0]))

        print(f"  Tenant ID : {tenant_id}")
        print(f"  Channel ID: {channel_id}")
        print()

        from app.services.notification_service import NotificationService

        async with AsyncSession(engine) as session:
            service = NotificationService(session)
            result = await service.test_channel(
                channel_id=uuid.UUID(channel_id),
                tenant_id=tenant_id,
            )

        if result.success:
            print(f"  ✅ test_channel OK")
            print(f"     Messaggio: {result.message}")
            print(f"     HTTP status: {result.http_status}")
        else:
            print(f"  ❌ test_channel FALLITO")
            print(f"     Motivo: {result.message}")
            print(f"     HTTP status: {result.http_status}")

        print()
        return result.success

    except Exception as exc:
        print(f"  ❌ Errore: {exc}")
        import traceback
        traceback.print_exc()
        return False


# ─── Main ─────────────────────────────────────────────────────────────────────

async def main() -> None:
    # Controlla se le credenziali sono passate via env (override manuale)
    manual_bot_token = os.environ.get("TELEGRAM_BOT_TOKEN")
    manual_chat_id = os.environ.get("TELEGRAM_CHAT_ID")

    if manual_bot_token and manual_chat_id:
        channel_id = None
        bot_token = manual_bot_token
        chat_id = manual_chat_id
        print("⚙️  Usando credenziali da variabili d'ambiente TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID")
        print()
    else:
        # Carica dal DB
        db_result = await load_channel_from_db()
        if not db_result:
            print("❌ Impossibile procedere: nessun canale Telegram configurato.")
            sys.exit(1)
        channel_id, bot_token, chat_id = db_result

    _banner(_mask_token(bot_token), chat_id)

    results: list[tuple[str, bool]] = []

    # STEP 2: invio diretto
    ok = await test_direct_send(bot_token, chat_id)
    results.append(("Invio diretto (send_message)", ok))

    # STEP 3: messaggio formattato
    ok = await test_send_test_message(bot_token, chat_id)
    results.append(("Messaggio di test formattato (send_test_message)", ok))

    # STEP 4: flusso completo via NotificationService (solo se abbiamo il channel_id dal DB)
    if channel_id:
        ok = await test_via_notification_service(channel_id)
        results.append(("Flusso completo (NotificationService.test_channel)", ok))

    # ── Riepilogo ────────────────────────────────────────────────────────────
    _sep("═")
    print("  RIEPILOGO TEST TELEGRAM")
    _sep("═")
    all_ok = True
    for name, success in results:
        icon = "✅" if success else "❌"
        print(f"  {icon}  {name}")
        if not success:
            all_ok = False
    _sep("═")
    print()

    if all_ok:
        print("🎉 Tutti i test Telegram superati con successo!")
    else:
        print("⚠️  Alcuni test Telegram sono falliti.")
        sys.exit(1)


if __name__ == "__main__":
    asyncio.run(main())
