"""
doit-fm CLI — the entry point for everything.

Commands
--------
  doitfm init       Guided setup wizard (2–3 minutes, guided step by step)
  doitfm run        Start the agent (usually done by the OS service)
  doitfm status     Show whether the agent is running
  doitfm update     Check for & apply updates from PyPI
  doitfm doctor     Diagnose installation problems
  doitfm stop       Stop the running agent
  doitfm uninstall  Remove the service (keeps config unless --purge)
"""
from __future__ import annotations

import asyncio
import os
import platform
import shutil
import subprocess
import sys
import time
from pathlib import Path

import click
from rich.console import Console
from rich.panel import Panel
from rich.prompt import Confirm, Prompt
from rich.table import Table

console = Console()


# ─── Helpers ─────────────────────────────────────────────────────────────────

def _ok(msg):   console.print(f"  [bold green]✓[/bold green]  {msg}")
def _err(msg):  console.print(f"  [bold red]✗[/bold red]  {msg}")
def _info(msg): console.print(f"  [yellow]→[/yellow]  {msg}")
def _head(msg): console.print(f"\n[bold cyan]{msg}[/bold cyan]")
def _blank():   console.print()

REQUIRED_DEPS = [
    ("telegram",     "python-telegram-bot"),
    ("aiohttp",      "aiohttp"),
    ("aiofiles",     "aiofiles"),
    ("aiosqlite",    "aiosqlite"),
    ("psutil",       "psutil"),
    ("click",        "click"),
    ("rich",         "rich"),
    ("cryptography", "cryptography"),
    ("apscheduler",  "APScheduler"),
    ("pypdf",        "pypdf"),
    ("PIL",          "Pillow"),
    ("qrcode",       "qrcode[pil]"),
]


def _dep_ok(import_name: str) -> bool:
    try:
        __import__(import_name)
        return True
    except ImportError:
        return False


# ─── CLI ─────────────────────────────────────────────────────────────────────

@click.group(invoke_without_command=True)
@click.version_option(package_name="doit-fm", prog_name="doitfm")
@click.pass_context
def cli(ctx):
    """🤖  doit-fm — AI-powered computer assistant, controlled via Telegram.\n
    \b
    First time?  Run:  doitfm init
    Already set up?    doitfm run
    Need a hand?       doitfm doctor
    """
    if ctx.invoked_subcommand is None:
        console.print(Panel.fit(
            "[bold cyan]doit-fm[/bold cyan] [dim]v2.1.0[/dim]\n\n"
            "Your AI-powered computer assistant, controlled via Telegram.\n\n"
            "[bold]Quick start:[/bold]\n"
            "  [cyan]doitfm init[/cyan]      — guided setup (~2 min)\n"
            "  [cyan]doitfm run[/cyan]       — start the agent\n"
            "  [cyan]doitfm status[/cyan]    — check if agent is running\n"
            "  [cyan]doitfm doctor[/cyan]    — diagnose problems\n"
            "  [cyan]doitfm update[/cyan]    — update to latest\n"
            "  [cyan]doitfm stop[/cyan]      — stop the agent\n"
            "  [cyan]doitfm --help[/cyan]    — full command list",
            title="Welcome to doit-fm",
            border_style="cyan",
        ))


# ─── doctor ──────────────────────────────────────────────────────────────────

@cli.command()
def doctor():
    """Diagnose your installation — auto-fixes most problems."""
    console.print(Panel.fit("Running diagnostics...", title="🩺  doit-fm doctor", border_style="yellow"))

    all_ok = True

    # Python version
    v = sys.version_info
    if v >= (3, 10):
        _ok(f"Python {v.major}.{v.minor}.{v.micro}")
    else:
        _err(f"Python {v.major}.{v.minor} detected — doit-fm requires Python ≥ 3.10")
        _info("Upgrade Python: https://python.org/downloads")
        all_ok = False

    # Dependencies
    _blank()
    _info("Checking dependencies...")
    missing = [(i, p) for i, p in REQUIRED_DEPS if not _dep_ok(i)]
    for imp, pkg in REQUIRED_DEPS:
        if _dep_ok(imp):
            _ok(pkg)
        else:
            _err(f"{pkg}  ← not installed")

    if missing:
        _blank()
        _info("Auto-installing missing packages...")
        pkgs = [p for _, p in missing]
        result = subprocess.run(
            [sys.executable, "-m", "pip", "install", "--quiet"] + pkgs,
            capture_output=True, text=True,
        )
        if result.returncode == 0:
            _ok(f"Installed: {', '.join(pkgs)}")
        else:
            _err("Auto-install failed:")
            console.print(result.stderr[:400])
            _info(f"Fix manually:  pip install {' '.join(pkgs)}")
            all_ok = False

    # Config
    _blank()
    _info("Checking config...")
    try:
        from doit_fm.core.config import BASE_DIR, DATA_DIR, LOG_DIR
        for d, label in [(BASE_DIR, "Config"), (DATA_DIR, "Data"), (LOG_DIR, "Logs")]:
            if d.exists():
                _ok(f"{label}: {d}")
            else:
                _info(f"{label} dir not created yet (will be on init): {d}")
    except Exception as e:
        _err(f"Config import error: {e}")
        all_ok = False

    try:
        from doit_fm.security.security import get_config
        c = get_config()
        if c.get("setup_complete"):
            _ok(f"Configured: AI={c.get('ai_provider','?')}/{c.get('ai_model','?')}")
        else:
            _info("Not configured yet — run: doitfm init")
    except Exception:
        _info("No config found — run: doitfm init")

    # Internet
    _blank()
    _info("Checking internet connectivity...")
    import socket
    try:
        socket.setdefaulttimeout(5)
        socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(("8.8.8.8", 53))
        _ok("Internet OK")
    except OSError:
        _err("No internet connection")
        all_ok = False

    # System
    _blank()
    import psutil
    _ok(f"Platform: {platform.system()} {platform.release()}")
    _ok(f"RAM: {psutil.virtual_memory().total / 1024**3:.1f} GB")
    _ok(f"Disk free: {psutil.disk_usage('/').free / 1024**3:.1f} GB")

    _blank()
    if all_ok:
        console.print("[bold green]✅  Everything looks good![/bold green]")
        _info("Run [cyan]doitfm init[/cyan] to set up, or [cyan]doitfm run[/cyan] if already configured.")
    else:
        console.print("[bold yellow]⚠️  Issues found — see above.[/bold yellow]")


# ─── init ────────────────────────────────────────────────────────────────────

@cli.command()
@click.option("--reconfigure", is_flag=True, help="Re-run setup even if already configured.")
def init(reconfigure):
    """Guided setup wizard — get running in about 2 minutes."""
    asyncio.run(_init_wizard(reconfigure))


async def _init_wizard(reconfigure: bool = False):
    from doit_fm.core.config import (
        BASE_DIR, DATA_DIR, LOG_DIR, PLUGIN_DIR, VERSION, AI_PROVIDERS,
    )
    from doit_fm.security.security import get_config, LockFile
    from doit_fm.persistence.database import get_db

    console.print(Panel.fit(
        f"[bold cyan]🤖  doit-fm  v{VERSION}[/bold cyan]\n\n"
        "Your AI-powered computer assistant — controlled via Telegram.\n\n"
        "  📁  Manage files and folders\n"
        "  💻  Monitor and control your computer\n"
        "  📅  Schedule recurring tasks automatically\n"
        "  🌐  Search the web, download files\n"
        "  🧠  Remember things, keep notes & to-dos\n"
        "  🛠  Git, Docker, run tests, SSH to servers\n"
        "  🖥  Screenshots, volume, open apps\n\n"
        "[dim]This wizard takes about 2 minutes.[/dim]",
        title="Welcome to doit-fm",
        border_style="cyan",
    ))
    _blank()

    cfg = get_config()
    if cfg.get("setup_complete") and not reconfigure:
        console.print("[green]✓  doit-fm is already configured.[/green]")
        _info("Start with [cyan]doitfm run[/cyan], or re-run with [cyan]doitfm init --reconfigure[/cyan] to change settings.")
        return

    # ── Step 1: Dependencies ──────────────────────────────────────────────
    _head("Step 1 of 5 — Checking dependencies")
    missing_deps = [(i, p) for i, p in REQUIRED_DEPS if not _dep_ok(i)]
    if missing_deps:
        _info(f"Installing {len(missing_deps)} missing package(s) automatically...")
        pkgs = [p for _, p in missing_deps]
        r = subprocess.run(
            [sys.executable, "-m", "pip", "install", "--quiet"] + pkgs,
            capture_output=True, text=True,
        )
        if r.returncode == 0:
            _ok(f"All dependencies ready: {', '.join(pkgs)}")
        else:
            _err(f"Failed to install: {', '.join(pkgs)}")
            console.print(r.stderr[:300])
            if not Confirm.ask("  Continue anyway?", default=False):
                return
    else:
        _ok("All dependencies already installed ✓")

    # ── Step 2: AI Provider ───────────────────────────────────────────────
    _blank()
    _head("Step 2 of 5 — Choose Your AI")
    console.print(
        "  doit-fm uses AI to understand your plain-English instructions.\n"
        "  Pick any provider you already have — or get a free one:\n"
    )

    provider_list = list(AI_PROVIDERS.keys())
    for i, key in enumerate(provider_list, 1):
        info    = AI_PROVIDERS[key]
        has_free = any(m.get("free") for m in info.get("models", []))
        local    = key == "ollama"
        suffix   = "  [green](free tier)[/green]" if has_free else ""
        suffix  += "  [blue](local, no API key needed)[/blue]" if local else ""
        console.print(f"    [cyan]{i}.[/cyan]  {info['name']}{suffix}")
    _blank()

    while True:
        choice = Prompt.ask("  Enter number", default="1")
        try:
            idx = int(choice) - 1
            if 0 <= idx < len(provider_list):
                break
        except ValueError:
            pass
        _err("Please enter a valid number.")

    provider_key  = provider_list[idx]
    provider_info = AI_PROVIDERS[provider_key]
    base_url      = provider_info.get("base_url", "")

    if provider_key == "custom":
        base_url = Prompt.ask("  Enter your API base URL (OpenAI-compatible)")

    models = provider_info.get("models", [])
    if models and provider_key != "custom":
        _blank()
        console.print(f"  Models for [cyan]{provider_info['name']}[/cyan]:")
        for i, m in enumerate(models, 1):
            tag = "[green]free[/green]" if m.get("free") else "[yellow]paid[/yellow]"
            console.print(f"    [cyan]{i}.[/cyan]  {m['label']}  ({m['id']})  [{tag}]")
        while True:
            mc = Prompt.ask("  Select model", default="1")
            try:
                mi = int(mc) - 1
                if 0 <= mi < len(models):
                    model_id = models[mi]["id"]
                    break
            except ValueError:
                pass
    else:
        model_id = Prompt.ask("  Enter model ID")

    console.print(f"\n  [bold cyan]{provider_info['name']}[/bold cyan] / [bold cyan]{model_id}[/bold cyan]\n")

    if provider_key == "ollama":
        api_key = "ollama"
        _ok("Ollama runs locally — no API key required")
    else:
        console.print("  [dim]Your key is stored encrypted on your computer. Never shared.[/dim]")
        console.print("  [dim]Tip: paste it and press Enter. It won't be displayed.[/dim]")
        while True:
            import getpass
            try:
                api_key = getpass.getpass("  API key: ").strip()
            except Exception:
                # Fallback: some environments can't do getpass
                api_key = Prompt.ask("  Paste your API key").strip()
            if not api_key:
                _err("Key cannot be empty — please paste your API key.")
                continue
            if len(api_key) < 8:
                _err("That looks too short for an API key. Please try again.")
                continue
            _ok(f"Key received ({len(api_key)} characters)")
            break

    _info("Testing AI connection (this may take a moment)...")
    ai_validated = False
    try:
        import aiohttp  # check before attempting
        from doit_fm.ai.engine import validate_api_key
        ok_ai, ai_msg = await validate_api_key(provider_key, model_id, api_key, base_url)
        if ok_ai:
            _ok(f"AI connected: {ai_msg}")
            ai_validated = True
        else:
            # Make error message user-friendly
            friendly = ai_msg
            if "Invalid API key" in ai_msg or "401" in ai_msg:
                friendly = "API key rejected. Double-check you copied the full key."
            elif "quota" in ai_msg.lower() or "429" in ai_msg.lower():
                friendly = "API quota exceeded. Check your billing on the provider's website."
            elif "connect" in ai_msg.lower() or "timeout" in ai_msg.lower():
                friendly = "Could not reach the AI provider. Check your internet connection."
            _err(f"Connection test failed: {friendly}")
            _info("You can fix this later with:  doitfm init --reconfigure")
            if not Confirm.ask("  Continue setup anyway?", default=True):
                return
    except ImportError:
        _info("Network libraries not yet installed — skipping live AI test.")
        _info("Run [cyan]doitfm doctor[/cyan] after setup to verify the connection.")
    except Exception as e:
        _err(f"Connection test error: {type(e).__name__}: {e}")
        _info("You can fix this later with:  doitfm init --reconfigure")
        if not Confirm.ask("  Continue setup anyway?", default=True):
            return

    # ── Step 3: Telegram ──────────────────────────────────────────────────
    _blank()
    _head("Step 3 of 5 — Connect Telegram")
    console.print(
        "  You need two things:\n\n"
        "  [bold]1. A bot token[/bold]  (30 seconds to create):\n"
        "       Open Telegram → search [cyan]@BotFather[/cyan] → send /newbot\n"
        "       Follow prompts, copy the token it gives you.\n\n"
        "  [bold]2. Your user ID[/bold]:\n"
        "       Open Telegram → search [cyan]@userinfobot[/cyan] → send /start\n"
        "       Copy the number it shows.\n"
    )

    while True:
        bot_token = Prompt.ask("  Bot token").strip()
        if not bot_token:
            _err("Token cannot be empty.")
            continue
        if ":" not in bot_token or len(bot_token) < 20:
            _err("That doesn't look right — bot tokens look like  123456789:ABCdefGHIjklMNOpqrSTUvwxYZ")
            if not Confirm.ask("  Try again?", default=True):
                break
            continue
        _info("Validating token with Telegram...")
        try:
            from doit_fm.telegram_bot.bot import validate_bot_token
        except ImportError:
            _info("Telegram library not yet installed — skipping live token check.")
            _ok("Token format looks correct — continuing.")
            break
        try:
            ok_tok, tok_info = await validate_bot_token(bot_token)
            if ok_tok:
                _ok(f"Bot validated: {tok_info}")
                break
            else:
                friendly_tok = tok_info
                if "Unauthorized" in tok_info or "401" in tok_info:
                    friendly_tok = "Token rejected by Telegram. Make sure you copied the full token from @BotFather."
                elif "connect" in tok_info.lower() or "timeout" in tok_info.lower():
                    friendly_tok = "Could not reach Telegram — check your internet connection."
                _err(f"Token problem: {friendly_tok}")
        except Exception as e:
            _err(f"Validation error: {type(e).__name__}: {e}")
        if not Confirm.ask("  Try a different token?", default=True):
            break

    while True:
        uid_str = Prompt.ask("  Your Telegram user ID (numbers only, from @userinfobot)").strip()
        if not uid_str:
            _err("User ID cannot be empty.")
            continue
        # Strip any accidental non-digit characters (spaces, dashes, etc.)
        uid_clean = "".join(c for c in uid_str if c.isdigit())
        try:
            telegram_user_id = int(uid_clean)
            if telegram_user_id < 1000:
                _err("That number looks too small. Telegram user IDs are at least 6 digits.")
                continue
            _ok(f"User ID: {telegram_user_id}")
            break
        except ValueError:
            _err("Must be a number, e.g. 123456789  (get it from @userinfobot in Telegram)")

    _info("Sending test message to your Telegram...")
    try:
        from doit_fm.telegram_bot.bot import send_test_message
    except ImportError:
        _info("Telegram library not yet installed — skipping test message.")
        _info("After setup, run [cyan]doitfm doctor[/cyan] to install everything.")
    else:
        try:
            ok_msg, msg_info = await send_test_message(bot_token, telegram_user_id)
            if ok_msg:
                _ok("Test message sent — check Telegram! 🎉")
            else:
                friendly_msg = msg_info
                if "chat not found" in msg_info.lower() or "400" in msg_info:
                    friendly_msg = (
                        "Could not find your chat. Open your bot in Telegram and "
                        "send /start to it first, then re-run doitfm init --reconfigure."
                    )
                elif "Forbidden" in msg_info or "403" in msg_info:
                    friendly_msg = "Bot can't message you yet. Open your bot in Telegram and tap Start first."
                _err(f"Test message failed: {friendly_msg}")
                _info("Fix: open your bot in Telegram → tap Start → re-run  doitfm init --reconfigure")
                if not Confirm.ask("  Continue setup anyway?", default=True):
                    return
        except Exception as e:
            _err(f"Test message error: {type(e).__name__}: {e}")
            _info("Usually OK — check Telegram after starting the agent.")

    # ── Step 4: System Setup ──────────────────────────────────────────────
    _blank()
    _head("Step 4 of 5 — System Preparation")

    for d, label in [
        (BASE_DIR,   "Config directory"),
        (DATA_DIR,   "Data directory"),
        (LOG_DIR,    "Logs directory"),
        (PLUGIN_DIR, "Plugins directory"),
    ]:
        try:
            d.mkdir(parents=True, exist_ok=True)
            _ok(f"{label}: {d}")
        except Exception as e:
            _err(f"{label} failed: {e}")

    db = None
    try:
        db = await get_db()
        _ok("Database initialized")
    except ImportError:
        _info("Database library (aiosqlite) not yet installed.")
        _info("Run [cyan]doitfm doctor[/cyan] to install it. Config will still be saved.")
    except Exception as e:
        _err(f"Database setup error: {e}")
        _info("Config will still be saved — run [cyan]doitfm doctor[/cyan] to fix.")

    cfg.set("ai_provider",      provider_key)
    cfg.set("ai_model",         model_id)
    cfg.set("ai_api_key",       api_key)
    cfg.set("ai_base_url",      base_url)
    cfg.set("telegram_token",   bot_token)
    cfg.set("telegram_user_id", telegram_user_id)
    cfg.set("trust_granted",    True)
    cfg.set("setup_complete",   True)
    if db:
        try:
            await db.config_set("version", VERSION)
        except Exception:
            pass  # Non-fatal — encrypted file config is already saved above
    _ok("Configuration saved (AES-256 encrypted)")

    try:
        from doit_fm.plugins.manager import write_example_plugin
        await write_example_plugin()
        _ok(f"Plugin directory ready: {PLUGIN_DIR}")
    except (ImportError, Exception):
        pass  # Non-essential — plugins work without this

    # ── Step 5: Auto-start service ────────────────────────────────────────
    _blank()
    _head("Step 5 of 5 — Auto-Start")
    os_label = {
        "linux":  "Linux (systemd)",
        "darwin": "macOS (LaunchAgent)",
        "win32":  "Windows (Task Scheduler)",
    }.get(sys.platform, sys.platform)
    console.print(f"  OS: [cyan]{os_label}[/cyan]")
    console.print("  If installed, doit-fm starts automatically when your computer boots.")
    _blank()

    install_svc = Confirm.ask("  Install auto-start service?", default=True)
    if install_svc:
        try:
            from doit_fm.services.service import install_service
            ok_svc, svc_msg = install_service()
            if ok_svc: _ok(svc_msg)
            else:      _err(svc_msg); _info("Start manually with:  doitfm run")
        except Exception as e:
            _err(f"Service install error: {e}")
            _info("Start manually with:  doitfm run")

    # ── Done ──────────────────────────────────────────────────────────────
    _blank()
    t = Table(title="✅  Setup Complete", border_style="green", show_header=False)
    t.add_column("Setting", style="cyan", no_wrap=True)
    t.add_column("Value")
    t.add_row("AI",          f"{provider_info['name']} / {model_id}")
    t.add_row("Telegram",    f"User ID {telegram_user_id}")
    t.add_row("Config",      str(BASE_DIR))
    t.add_row("Auto-start",  "Yes ✓" if install_svc else "No — use doitfm run")
    console.print(t)

    _blank()
    console.print(Panel.fit(
        "[bold green]🎉  doit-fm is ready![/bold green]\n\n"
        + ("The agent will start automatically on next boot.\n" if install_svc else
           "Start it now with:  [cyan]doitfm run[/cyan]\n")
        + "\n"
        "Then open Telegram and just talk naturally:\n"
        "  _'show me what's in my Downloads folder'_\n"
        "  _'remind me in 30 minutes'_\n"
        "  _'what's taking up the most space on my disk?'_\n"
        "  _'backup my Documents to an external drive'_\n\n"
        "Type [cyan]/help[/cyan] in Telegram for the full list.",
        border_style="green",
    ))

    _blank()
    if Confirm.ask("  Start doit-fm right now?", default=True):
        console.print("[dim]Starting... (safe to close this terminal)[/dim]")
        await _run_agent()


# ─── run ─────────────────────────────────────────────────────────────────────

@cli.command()
def run():
    """Start the doit-fm agent."""
    asyncio.run(_run_agent())


async def _run_agent():
    import logging
    from doit_fm.core.config import VERSION
    from doit_fm.security.security import get_config, LockFile, AuthorizationManager
    from doit_fm.persistence.database import get_db
    from doit_fm.ai.engine import AIEngine
    from doit_fm.telegram_bot.bot import TelegramBot
    from doit_fm.task_engine.engine import get_engine
    from doit_fm.scheduler.scheduler import get_scheduler
    from doit_fm.plugins.manager import get_plugin_manager
    from doit_fm.supervisor.supervisor import Supervisor, HealthMonitor
    from doit_fm.logging_system.logger import setup_logging

    setup_logging()
    logger = logging.getLogger("doit_fm.main")

    lock = LockFile()
    if not lock.acquire():
        console.print("[red]doit-fm is already running.[/red]")
        _info("Check with [cyan]doitfm status[/cyan]  or stop with [cyan]doitfm stop[/cyan]")
        sys.exit(1)

    cfg = get_config()
    if not cfg.get("setup_complete"):
        console.print("[red]Not configured yet.[/red]")
        _info("Run:  [cyan]doitfm init[/cyan]")
        lock.release()
        sys.exit(1)

    logger.info("doit-fm v%s starting", VERSION)
    db = await get_db()
    await db.audit("agent_start", details={"version": VERSION})

    ai     = AIEngine(cfg.all())
    auth   = AuthorizationManager(cfg)
    engine = get_engine()
    await engine.start()

    sched = get_scheduler()
    await sched.start()

    pm = get_plugin_manager()
    loaded = await pm.discover_and_load()
    if loaded:
        logger.info("Plugins: %s", loaded)

    def _safe_cb(mode: bool):
        if mode: engine.enter_safe_mode()
        else:    engine.exit_safe_mode()

    bot = TelegramBot(
        token=cfg.get("telegram_token"),
        auth=auth,
        ai_engine=ai,
        safe_mode_callback=_safe_cb,
    )

    async def _startup_notify():
        await asyncio.sleep(4)
        await bot.send_message(
            f"🤖 doit-fm v{VERSION} is online!\n\n"
            "Just talk to me naturally — I understand plain English.\n"
            "Type /help to see everything I can do."
        )

    asyncio.create_task(_startup_notify())

    supervisor = Supervisor()
    supervisor.add_component("telegram_bot",   bot.start)
    supervisor.add_component("health_monitor", HealthMonitor(notify_callback=bot.send_message).run)

    try:
        await supervisor.run()
    finally:
        await engine.stop()
        await sched.stop()
        await db.audit("agent_stop")
        await db.close()
        lock.release()
        logger.info("doit-fm stopped cleanly.")


# ─── status ──────────────────────────────────────────────────────────────────

@cli.command()
def status():
    """Show whether doit-fm is running."""
    try:
        from doit_fm.services.service import service_status
        running, status_str = service_status()
        icon = "🟢" if running else "🔴"
        console.print(f"{icon}  doit-fm: {status_str}")
        if not running:
            _info("Start it:  doitfm run")
    except Exception as e:
        _err(f"Could not check status: {e}")
        _info("Run [cyan]doitfm doctor[/cyan] to diagnose.")


# ─── update ──────────────────────────────────────────────────────────────────

@cli.command()
@click.option("--yes", "-y", is_flag=True, help="Skip confirmation.")
def update(yes):
    """Check for updates and upgrade to latest version."""
    asyncio.run(_do_update(yes))


async def _do_update(auto_confirm: bool = False):
    _info("Checking PyPI for the latest version...")
    try:
        import aiohttp
        from doit_fm.core.config import VERSION as current

        async with aiohttp.ClientSession() as sess:
            async with sess.get(
                "https://pypi.org/pypi/doit-fm/json",
                timeout=aiohttp.ClientTimeout(total=10),
            ) as resp:
                if resp.status != 200:
                    _err(f"PyPI returned HTTP {resp.status}")
                    return
                data = await resp.json()

        latest = data["info"]["version"]
        console.print(f"  Current: [cyan]{current}[/cyan]  →  Latest: [cyan]{latest}[/cyan]")

        if latest == current:
            console.print("[green]✓  Already up to date![/green]")
            return

        if auto_confirm or Confirm.ask(f"  Update to v{latest}?", default=True):
            _info("Updating...")
            r = subprocess.run(
                [sys.executable, "-m", "pip", "install", "--upgrade", "--quiet", "doit-fm"],
                capture_output=True, text=True,
            )
            if r.returncode == 0:
                _ok(f"Updated to v{latest}!")
                _info("Restart with:  doitfm stop && doitfm run")
            else:
                _err("Update failed:")
                console.print(r.stderr[:400])
    except Exception as e:
        _err(f"Update check failed: {e}")
        _info("Manual update:  pip install --upgrade doit-fm")


# ─── stop ────────────────────────────────────────────────────────────────────

@cli.command()
def stop():
    """Stop the running doit-fm agent."""
    import signal
    try:
        from doit_fm.core.config import LOCK_FILE
        if not LOCK_FILE.exists():
            _info("doit-fm does not appear to be running.")
            return
        pid_text = LOCK_FILE.read_text().strip()
        try:
            pid = int(pid_text)
            os.kill(pid, signal.SIGTERM)
            time.sleep(1)
            _ok(f"Stopped (PID {pid})")
        except (ValueError, ProcessLookupError):
            LOCK_FILE.unlink(missing_ok=True)
            _info("Stale lock file removed.")
    except Exception as e:
        _err(f"Stop failed: {e}")


# ─── uninstall ────────────────────────────────────────────────────────────────

@cli.command()
@click.option("--purge", is_flag=True, help="Also delete all config, data and logs.")
def uninstall(purge):
    """Remove doit-fm service (keeps data unless --purge)."""
    try:
        from doit_fm.services.service import uninstall_service
        ok_svc, msg = uninstall_service()
        if ok_svc: _ok(msg)
        else:      _err(msg)
    except Exception as e:
        _err(f"Service removal: {e}")

    if purge or Confirm.ask("  Also delete all config and data?", default=False):
        try:
            from doit_fm.core.config import BASE_DIR
            shutil.rmtree(str(BASE_DIR), ignore_errors=True)
            _ok(f"Deleted: {BASE_DIR}")
        except Exception as e:
            _err(f"Cleanup error: {e}")

    _ok("doit-fm removed from your system.")
    _info("To fully remove the package:  pip uninstall doit-fm")


if __name__ == "__main__":
    cli()
