#!/usr/bin/env python3
"""
CLI for running Mothership bots
"""
import sys
import os
import asyncio
import signal
import importlib.util
from pathlib import Path
from typing import Optional

from .bot_factory import BotFactory
from .firebase import FirebaseClient
from aiohttp import web


async def run_bot(bot_path: str, port: int = 3000):
    """
    Run a bot from a Python file or module

    Args:
        bot_path: Path to bot file or module name
        port: Port for health check server (default: 3000)
    """
    # Load .env file from current working directory
    try:
        from dotenv import load_dotenv
        env_path = Path.cwd() / ".env"
        if env_path.exists():
            print(f"Loading environment from {env_path}")
            load_dotenv(env_path)
        else:
            # Try loading from default location
            load_dotenv()
    except ImportError:
        pass  # python-dotenv not installed

    loop = asyncio.get_running_loop()
    stop_event = asyncio.Event()

    def handle_signal():
        print("\n\nReceived shutdown signal...")
        stop_event.set()

    # Register signal handlers
    for sig in (signal.SIGINT, signal.SIGTERM):
        loop.add_signal_handler(sig, handle_signal)

    # Load bot module
    bot_file = Path(bot_path)
    if not bot_file.exists():
        # Try as module path (e.g., "bots.ping_bot")
        bot_file = Path.cwd() / "bots" / bot_path / "__init__.py"
        if not bot_file.exists():
            print(f"Error: Bot not found at '{bot_path}' or 'bots/{bot_path}'")
            sys.exit(1)

    print(f"Loading bot: {bot_file}")

    # Import bot module
    spec = importlib.util.spec_from_file_location("bot_module", bot_file)
    if not spec or not spec.loader:
        print(f"Error: Cannot load bot from {bot_file}")
        sys.exit(1)

    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)

    if not hasattr(module, "bot"):
        print(f"Error: Bot module must export 'bot' definition")
        sys.exit(1)

    bot_definition = module.bot

    # Initialize Firebase if configured
    firebase_project_id = os.getenv("FIREBASE_PROJECT_ID")
    if firebase_project_id:
        try:
            FirebaseClient.initialize(firebase_project_id)
            print(f"✓ Firebase initialized (project: {firebase_project_id})")
        except Exception as e:
            print(f"⚠ Firebase initialization failed: {e}")
            print("Continuing with in-memory storage...")

    # Create bot instance
    try:
        instance = BotFactory.create(bot_definition)
    except Exception as e:
        print(f"Error creating bot: {e}")
        sys.exit(1)

    runner: Optional[web.AppRunner] = None

    try:
        # Start bot
        await instance.start()

        # Start polling
        instance.logger.info(f"Starting polling on port {port}...")
        await instance.app.updater.start_polling()

        # Create health check server
        app = web.Application()

        async def health_check(request: web.Request) -> web.Response:
            return web.Response(text="OK")

        app.router.add_get("/", health_check)
        app.router.add_get("/health", health_check)

        # Start server
        runner = web.AppRunner(app)
        await runner.setup()
        site = web.TCPSite(runner, "0.0.0.0", port)
        await site.start()

        instance.logger.success(f"Bot running on http://localhost:{port}")
        print("\nPress Ctrl+C to stop...")

        # Wait for shutdown signal
        await stop_event.wait()

    except Exception as e:
        print(f"\nError during execution: {e}")
    finally:
        print("Shutting down...")

        # Stop polling first
        try:
            if instance.app.updater.running:
                print("Stopping updater...")
                await asyncio.wait_for(instance.app.updater.stop(), timeout=2.0)
        except asyncio.TimeoutError:
            print("Updater stop timed out, forcing shutdown...")
        except Exception as e:
            print(f"Error stopping updater: {e}")

        # Clean up web server
        if runner:
            try:
                print("Cleaning up web server...")
                await runner.cleanup()
            except Exception as e:
                print(f"Error cleaning up web server: {e}")

        # Stop the bot
        try:
            print("Stopping bot...")
            await instance.stop()
        except Exception as e:
            print(f"Error stopping bot: {e}")

        print("Bot stopped")


def list_bots():
    """List available bots in the bots directory"""
    bots_dir = Path.cwd() / "bots"
    if not bots_dir.exists():
        print("No 'bots' directory found in current working directory")
        return

    print("Available bots:")
    found = False
    for bot_dir in sorted(bots_dir.iterdir()):
        if bot_dir.is_dir() and not bot_dir.name.startswith("_"):
            init_file = bot_dir / "__init__.py"
            if init_file.exists():
                print(f"  - {bot_dir.name}")
                found = True

    if not found:
        print("  No bots found")


def main():
    """Main CLI entry point"""
    import argparse

    parser = argparse.ArgumentParser(
        description="Mothership Bot CLI - Run Telegram bots locally",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  mothership run ping_bot              # Run bot from bots/ping_bot/
  mothership run bots/my_bot/__init__.py  # Run bot from specific file
  mothership run ping_bot --port 8080  # Run on custom port
  mothership list                      # List available bots
        """
    )

    subparsers = parser.add_subparsers(dest="command", help="Command to run")

    # Run command
    run_parser = subparsers.add_parser("run", help="Run a bot")
    run_parser.add_argument("bot", help="Bot name or path to bot file")
    run_parser.add_argument("--port", type=int, default=3000, help="Port for health check server (default: 3000)")

    # List command
    subparsers.add_parser("list", help="List available bots")

    args = parser.parse_args()

    if args.command == "run":
        try:
            asyncio.run(run_bot(args.bot, args.port))
        except KeyboardInterrupt:
            pass
    elif args.command == "list":
        list_bots()
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
