import os
import sys
import time

from .db import get_db, now
from .discovery import discover_agents, scan_processes
from .display import STATUS_ICON, STATUS_LABEL, format_agents, format_bar, print_agents


def cmd_default(_args):
    db = get_db()
    discover_agents(db)
    print_agents(db)
    db.close()


def cmd_list(args):
    db = get_db()
    if not getattr(args, "no_scan", False):
        discover_agents(db)
    print_agents(db)
    db.close()


def cmd_watch(args):
    interval = getattr(args, "interval", 2) or 2
    sys.stdout.write("\033[?1049h")
    sys.stdout.flush()
    try:
        while True:
            sys.stdout.write("\033[H")
            sys.stdout.flush()
            db = get_db()
            discover_agents(db)
            output = format_agents(db)
            db.close()
            for line in output.split("\n"):
                sys.stdout.write(line + "\033[K\n")
            sys.stdout.write("\033[J")
            sys.stdout.flush()
            time.sleep(interval)
    except KeyboardInterrupt:
        pass
    finally:
        sys.stdout.write("\033[?1049l")
        sys.stdout.flush()


def cmd_scan(_args):
    processes = scan_processes()
    if not processes:
        print("No AI agent processes found running.")
        return

    print(f"\n  Found {len(processes)} agent process(es):\n")
    for p in processes:
        children_str = "yes" if p.get("has_children") else "no"
        status = "idle? (sleeping + low CPU + no children)" if p["waiting"] else "running"
        print(f"  PID {p['pid']:>7}  {p['type']:<8}  {p['name']}")
        print(f"                state: {p['state']}  cpu: {p['cpu']:.1f}%  children: {children_str}  status: {status}")
        if p["cwd"]:
            print(f"                cwd: {p['cwd']}")
        print()

    db = get_db()
    discover_agents(db, processes=processes)
    db.close()
    print("  ✓ Synced to database")


def cmd_add(args):
    db = get_db()
    ts = now()
    cur = db.execute(
        "INSERT INTO agents (name, type, status, summary, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)",
        (args.name, args.type, args.status, args.summary or "", ts, ts),
    )
    db.commit()
    db.close()
    print(f"✓ Agent #{cur.lastrowid} added: {args.name} ({args.type}, {args.status})")


def cmd_update(args):
    db = get_db()
    agent = db.execute("SELECT * FROM agents WHERE id = ?", (args.id,)).fetchone()
    if not agent:
        print(f"✗ Agent #{args.id} not found"); sys.exit(1)

    fields, vals = [], []
    if args.status:
        fields.append("status = ?"); vals.append(args.status)
    if args.summary:
        fields.append("summary = ?"); vals.append(args.summary)
    if args.name:
        fields.append("name = ?"); vals.append(args.name)
    if args.type:
        fields.append("type = ?"); vals.append(args.type)

    if not fields:
        print("Nothing to update."); return

    fields.append("updated_at = ?"); vals.append(now()); vals.append(args.id)
    db.execute(f"UPDATE agents SET {', '.join(fields)} WHERE id = ?", vals)
    db.commit()
    db.close()
    print(f"✓ Agent #{args.id} updated")


def cmd_done(args):
    db = get_db()
    agent = db.execute("SELECT * FROM agents WHERE id = ?", (args.id,)).fetchone()
    if not agent:
        print(f"✗ Agent #{args.id} not found"); sys.exit(1)
    db.execute("UPDATE agents SET status = 'done', updated_at = ? WHERE id = ?", (now(), args.id))
    db.commit()
    db.close()
    print(f"✓ Agent #{args.id} marked done")


def cmd_todo(args):
    db = get_db()
    agent = db.execute("SELECT * FROM agents WHERE id = ?", (args.agent_id,)).fetchone()
    if not agent:
        print(f"✗ Agent #{args.agent_id} not found"); sys.exit(1)
    cur = db.execute(
        "INSERT INTO todos (agent_id, description, created_at) VALUES (?, ?, ?)",
        (args.agent_id, args.description, now()),
    )
    db.commit()
    db.close()
    print(f"✓ Todo #{cur.lastrowid} added to agent #{args.agent_id}")


def cmd_todo_done(args):
    db = get_db()
    todo = db.execute(
        "SELECT * FROM todos WHERE id = ? AND agent_id = ?", (args.todo_id, args.agent_id)
    ).fetchone()
    if not todo:
        print(f"✗ Todo #{args.todo_id} not found for agent #{args.agent_id}"); sys.exit(1)
    db.execute("UPDATE todos SET completed = 1 WHERE id = ?", (args.todo_id,))
    db.commit()
    db.close()
    print(f"✓ Todo #{args.todo_id} completed")


def cmd_show(args):
    db = get_db()
    agent = db.execute("SELECT * FROM agents WHERE id = ?", (args.id,)).fetchone()
    if not agent:
        print(f"✗ Agent #{args.id} not found"); sys.exit(1)

    icon = STATUS_ICON.get(agent["status"], "❓")
    status_str = STATUS_LABEL.get(agent["status"], agent["status"])
    source = "auto-discovered" if agent["auto_discovered"] else "manual"

    print(f"\n  Agent #{agent['id']}: {agent['name']}")
    print(f"  Type:    {agent['type']}")
    print(f"  Source:  {source}")
    print(f"  Status:  {icon} {status_str}")
    if agent["pid"]:
        print(f"  PID:     {agent['pid']}")
    if agent["cwd"]:
        print(f"  CWD:     {agent['cwd']}")
    print(f"  Summary: {agent['summary'] or '(none)'}")
    print(f"  Created: {agent['created_at']}")
    print(f"  Updated: {agent['updated_at']}")
    if agent["status"] == "waiting" and agent["auto_discovered"]:
        print("  Note:    'idle?' is a heuristic based on sleeping state, low CPU, and no network activity.")

    todos = db.execute(
        "SELECT * FROM todos WHERE agent_id = ? ORDER BY completed, id", (args.id,)
    ).fetchall()
    if todos:
        print(f"\n  Todos:")
        for t in todos:
            check = "✓" if t["completed"] else "○"
            print(f"    [{check}] #{t['id']} {t['description']}")
    db.close()
    print()


def cmd_rm(args):
    db = get_db()
    agent = db.execute("SELECT * FROM agents WHERE id = ?", (args.id,)).fetchone()
    if not agent:
        print(f"✗ Agent #{args.id} not found"); sys.exit(1)
    db.execute("DELETE FROM todos WHERE agent_id = ?", (args.id,))
    db.execute("DELETE FROM agents WHERE id = ?", (args.id,))
    db.commit()
    db.close()
    print(f"✓ Agent #{args.id} removed")


def cmd_kill(args):
    import signal
    db = get_db()
    agent = db.execute("SELECT * FROM agents WHERE id = ?", (args.id,)).fetchone()
    if not agent:
        print(f"✗ Agent #{args.id} not found"); sys.exit(1)
    if not agent["pid"]:
        print(f"✗ Agent #{args.id} has no PID (manual entry?)"); sys.exit(1)

    pid = agent["pid"]
    try:
        os.kill(pid, signal.SIGTERM)
        db.execute("UPDATE agents SET status = 'done', updated_at = ? WHERE id = ?", (now(), args.id))
        db.commit()
        print(f"✓ Sent SIGTERM to agent #{args.id} (PID {pid})")
    except ProcessLookupError:
        db.execute("UPDATE agents SET status = 'done', updated_at = ? WHERE id = ?", (now(), args.id))
        db.commit()
        print(f"✗ PID {pid} already exited — marked as done")
    except PermissionError:
        print(f"✗ Permission denied to kill PID {pid}")
    db.close()


def cmd_top(args):
    from .tui import run_tui
    interval = getattr(args, "interval", 2) or 2
    run_tui(interval)


def cmd_bar(args):
    interval = getattr(args, "interval", None)
    watch = getattr(args, "watch", False)

    if watch and interval:
        try:
            while True:
                db = get_db()
                discover_agents(db)
                line = format_bar(db)
                db.close()
                sys.stdout.write(f"\r\033[K{line}")
                sys.stdout.flush()
                time.sleep(interval)
        except KeyboardInterrupt:
            print()
    else:
        db = get_db()
        discover_agents(db)
        print(format_bar(db))
        db.close()


def cmd_clear(_args):
    db = get_db()
    db.execute("DELETE FROM todos")
    db.execute("DELETE FROM agents")
    db.commit()
    db.close()
    print("✓ All agents cleared")
