"""Echo Core — main entry point."""

import asyncio
import logging
import os
import signal
import sys
from pathlib import Path

# Ensure project root is on sys.path so `src.*` imports work
PROJECT_ROOT = Path(__file__).resolve().parent.parent
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

from src.config import load_config
from src.credential_store import get_secret
from src.adapters.discord_bot import create_bot, split_message
from src.scheduler import Scheduler

PID_FILE = PROJECT_ROOT / "echo-core.pid"
LOG_DIR = PROJECT_ROOT / "logs"


def setup_logging():
    LOG_DIR.mkdir(parents=True, exist_ok=True)
    fmt = "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
    logging.basicConfig(
        level=logging.INFO,
        format=fmt,
        handlers=[
            logging.FileHandler(LOG_DIR / "echo-core.log"),
            logging.StreamHandler(sys.stderr),
        ],
    )

    # Security log — separate file for unauthorized access attempts
    security_handler = logging.FileHandler(LOG_DIR / "security.log")
    security_handler.setFormatter(logging.Formatter(fmt))
    security_logger = logging.getLogger("echo-core.security")
    security_logger.addHandler(security_handler)

    # Invocation log — all Claude CLI calls
    invoke_handler = logging.FileHandler(LOG_DIR / "echo-core.log")
    invoke_handler.setFormatter(logging.Formatter(fmt))
    invoke_logger = logging.getLogger("echo-core.invoke")
    invoke_logger.addHandler(invoke_handler)


def main():
    setup_logging()
    logger = logging.getLogger("echo-core")

    token = get_secret("discord_token")
    if not token:
        logger.error(
            "discord_token not found in keyring. "
            "Run: python cli.py secrets set discord_token"
        )
        sys.exit(1)

    config = load_config()
    client = create_bot(config)

    # Scheduler setup
    async def _send_to_channel(channel_alias: str, text: str) -> None:
        """Callback: resolve alias and send text to Discord channel."""
        channels = config.get("channels", {})
        ch_info = channels.get(channel_alias)
        if not ch_info:
            logger.warning("Cron: unknown channel alias '%s'", channel_alias)
            return
        channel_id = ch_info.get("id")
        channel = client.get_channel(int(channel_id))
        if channel is None:
            logger.warning("Cron: channel %s not found in Discord cache", channel_id)
            return
        logger.info("Cron: sending %d chars to channel %s (%s)", len(text), channel_alias, channel_id)
        chunks = split_message(text)
        for chunk in chunks:
            await channel.send(chunk)
        logger.info("Cron: sent successfully to %s", channel_alias)

    scheduler = Scheduler(send_callback=_send_to_channel, config=config)
    client.scheduler = scheduler  # type: ignore[attr-defined]

    # Telegram bot (optional — only if telegram_token exists)
    telegram_token = get_secret("telegram_token")
    telegram_app = None
    if telegram_token:
        from src.adapters.telegram_bot import create_telegram_bot
        telegram_app = create_telegram_bot(config, telegram_token)
        logger.info("Telegram bot configured")
    else:
        logger.info("No telegram_token — Telegram bot disabled")

    # WhatsApp adapter (optional — only if whatsapp is enabled in config)
    whatsapp_enabled = config.get("whatsapp", {}).get("enabled", False)
    whatsapp_bridge_url = config.get("whatsapp", {}).get("bridge_url", "http://127.0.0.1:8098")
    if whatsapp_enabled:
        logger.info("WhatsApp adapter configured (bridge: %s)", whatsapp_bridge_url)
    else:
        logger.info("WhatsApp adapter disabled")

    # PID file
    PID_FILE.write_text(str(os.getpid()))

    # Signal handlers for graceful shutdown
    loop = asyncio.new_event_loop()

    def handle_signal(sig, frame):
        logger.info("Received signal %s, shutting down...", sig)
        loop.create_task(scheduler.stop())
        loop.create_task(client.close())

    signal.signal(signal.SIGTERM, handle_signal)
    signal.signal(signal.SIGINT, handle_signal)

    async def _run_all():
        """Run Discord + Telegram + WhatsApp bots concurrently."""
        tasks = [asyncio.create_task(client.start(token))]
        if telegram_app:
            async def _run_telegram():
                await telegram_app.initialize()
                await telegram_app.start()
                await telegram_app.updater.start_polling()
                logger.info("Telegram bot started polling")
                try:
                    while True:
                        await asyncio.sleep(3600)
                except asyncio.CancelledError:
                    await telegram_app.updater.stop()
                    await telegram_app.stop()
                    await telegram_app.shutdown()
            tasks.append(asyncio.create_task(_run_telegram()))
        if whatsapp_enabled:
            from src.adapters.whatsapp import run_whatsapp, stop_whatsapp
            async def _run_whatsapp():
                try:
                    await run_whatsapp(config, whatsapp_bridge_url)
                except asyncio.CancelledError:
                    stop_whatsapp()
            tasks.append(asyncio.create_task(_run_whatsapp()))
        await asyncio.gather(*tasks)

    try:
        loop.run_until_complete(_run_all())
    except KeyboardInterrupt:
        loop.run_until_complete(scheduler.stop())
        loop.run_until_complete(client.close())
    finally:
        PID_FILE.unlink(missing_ok=True)
        logger.info("Echo Core shut down.")


if __name__ == "__main__":
    main()
