#!/usr/bin/env python3
"""
LuckBot Agent — Combined entrypoint for Telegram + Swarm Protocol.

Runs Telegram bot + multiple Swarm agents as concurrent asyncio tasks.
Either service is optional, controlled by environment variables:
  - TELEGRAM_BOT_TOKEN: enables Telegram bot
  - SWARM_AGENTS: JSON array of agent configs (multi-agent)
  - SWARM_HUB_URL + SWARM_AGENT_ID: single agent fallback

Usage:
    python luckbot_main.py
"""

import os
import sys
import json
import asyncio
import logging
from pathlib import Path
from dotenv import load_dotenv

# Load .env — try local first (standalone dev), then backend sibling (repo layout).
# In Docker, env vars come from docker-compose env_file so this is a no-op.
_env_local = Path(__file__).parent / ".env"
_env_backend = Path(__file__).parent.parent / "backend" / ".env"
load_dotenv(_env_local if _env_local.exists() else _env_backend)

logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    level=logging.INFO,
)
logger = logging.getLogger("luckbot")

# Retry config for Swarm connectors
SWARM_RETRY_DELAY = 30  # seconds between retries
SWARM_MAX_RETRIES = 0   # 0 = infinite


def parse_swarm_agents() -> list[dict]:
    """Parse Swarm agent configs from environment.

    Supports two formats:

    1. Multi-agent (preferred):
       SWARM_AGENTS='[
         {"name":"LuckBot","type":"Trading","agent_id":"xxx","api_key":"yyy"},
         {"name":"LuckBot-Dev","type":"Development","agent_id":"aaa","api_key":"bbb"},
         {"name":"LuckBot-Quant","type":"Research","agent_id":"ccc","api_key":"ddd"}
       ]'

    2. Single-agent fallback (backward compatible):
       SWARM_HUB_URL=https://swarm.perkos.xyz
       SWARM_AGENT_ID=xxx
       SWARM_API_KEY=yyy
       SWARM_AGENT_NAME=LuckBot
       SWARM_AGENT_TYPE=Trading
    """
    hub_url = os.environ.get("SWARM_HUB_URL", "")
    org_id = os.environ.get("SWARM_ORG_ID", "")

    if not hub_url:
        return []

    # Try multi-agent JSON first
    agents_json = os.environ.get("SWARM_AGENTS", "")
    if agents_json:
        try:
            agents = json.loads(agents_json)
            for a in agents:
                a.setdefault("hub_url", hub_url)
                a.setdefault("org_id", org_id)
            return agents
        except json.JSONDecodeError as e:
            logger.error(f"Failed to parse SWARM_AGENTS JSON: {e}")
            return []

    # Fallback: single agent from individual env vars
    agent_id = os.environ.get("SWARM_AGENT_ID", "")
    api_key = os.environ.get("SWARM_API_KEY", "")
    if agent_id and api_key:
        return [{
            "hub_url": hub_url,
            "org_id": org_id,
            "name": os.environ.get("SWARM_AGENT_NAME", "LuckBot"),
            "type": os.environ.get("SWARM_AGENT_TYPE", "Trading"),
            "agent_id": agent_id,
            "api_key": api_key,
        }]

    return []


async def run_telegram_bot():
    """Start the Telegram bot using non-blocking API for asyncio compatibility."""
    from telegram import Update
    from telegram_bot import build_telegram_app

    app = build_telegram_app()

    async with app:
        await app.start()
        await app.updater.start_polling(allowed_updates=Update.ALL_TYPES)
        logger.info("Telegram bot running")

        # Keep running until cancelled
        stop_event = asyncio.Event()
        try:
            await stop_event.wait()
        except asyncio.CancelledError:
            pass
        finally:
            await app.updater.stop()
            await app.stop()
            logger.info("Telegram bot stopped")


async def run_swarm_agent(agent_config: dict):
    """Start a single Swarm agent with automatic retry on failure.

    Failures never propagate — retries forever so other services are unaffected.
    """
    from swarm_connector import SwarmConnector

    name = agent_config["name"]
    agent_type = agent_config["type"]

    attempt = 0
    while True:
        attempt += 1
        connector = SwarmConnector(
            hub_url=agent_config["hub_url"],
            org_id=agent_config["org_id"],
            agent_name=name,
            agent_type=agent_type,
            api_key=agent_config["api_key"],
            agent_id=agent_config["agent_id"],
        )

        try:
            await connector.run()
        except asyncio.CancelledError:
            await connector.stop()
            return
        except Exception as e:
            logger.error(f"Swarm agent '{name}' ({agent_type}) failed (attempt {attempt}): {e}")

            if SWARM_MAX_RETRIES and attempt >= SWARM_MAX_RETRIES:
                logger.error(f"Swarm agent '{name}' max retries — giving up")
                return

            logger.info(f"Swarm agent '{name}' will retry in {SWARM_RETRY_DELAY}s...")
            await asyncio.sleep(SWARM_RETRY_DELAY)


async def main():
    tasks = []

    # Telegram
    telegram_token = os.environ.get("TELEGRAM_BOT_TOKEN")
    if telegram_token:
        logger.info("Telegram bot enabled")
        tasks.append(run_telegram_bot())
    else:
        logger.info("Telegram bot disabled (no TELEGRAM_BOT_TOKEN)")

    # Swarm agents (one or more)
    agents = parse_swarm_agents()
    for agent in agents:
        name = agent.get("name", "?")
        agent_type = agent.get("type", "?")
        logger.info(f"Swarm agent enabled: {name} ({agent_type})")
        tasks.append(run_swarm_agent(agent))

    if not agents:
        logger.info("Swarm connector disabled (no SWARM_HUB_URL or agents)")

    if not tasks:
        logger.error("No services configured. Set TELEGRAM_BOT_TOKEN and/or SWARM_* in .env")
        sys.exit(1)

    logger.info(f"LuckBot starting with {len(tasks)} service(s)")

    # return_exceptions=True ensures one task crashing never kills the others
    results = await asyncio.gather(*tasks, return_exceptions=True)

    for r in results:
        if isinstance(r, Exception):
            logger.error(f"Service exited with error: {r}")

    logger.info("All services stopped")


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