"""CLI for ag2tracer — launch, stop, status, logs."""

import argparse
import os
import signal
import subprocess
import sys
import time
from pathlib import Path
from typing import Optional


def _config_dir() -> Path:
    d = Path.home() / ".ag2tracer"
    d.mkdir(exist_ok=True)
    return d


def _pid_file() -> Path:
    return _config_dir() / "server.pid"


def _log_dir() -> Path:
    d = _config_dir() / "logs"
    d.mkdir(exist_ok=True)
    return d


def _log_file() -> Path:
    return _log_dir() / "server.log"


def _running_pid() -> Optional[int]:
    pf = _pid_file()
    if not pf.exists():
        return None
    try:
        pid = int(pf.read_text().strip())
        os.kill(pid, 0)
        return pid
    except (ValueError, ProcessLookupError, PermissionError):
        pf.unlink(missing_ok=True)
        return None


def _find_frontend() -> Optional[Path]:
    pkg_dir = Path(__file__).parent
    dist = pkg_dir / "frontend"
    return dist if dist.exists() else None


def launch(host: str = "127.0.0.1", port: int = 8500, daemon: bool = False):
    """Launch the ag2tracer web interface."""
    if daemon:
        pid = _running_pid()
        if pid:
            print(f"Server already running (PID: {pid}). Stop it first: ag2tracer stop")
            sys.exit(1)

    frontend = _find_frontend()
    if not frontend:
        print("Error: Frontend assets not found.")
        sys.exit(1)

    if daemon:
        log = _log_file()
        pf = _pid_file()

        print(f"Starting ag2tracer in background...")
        print(f"  URL:  http://{host}:{port}")
        print(f"  Logs: {log}")

        cmd = [
            sys.executable, "-m", "uvicorn",
            "ag2tracer.api:app",
            "--host", host,
            "--port", str(port),
        ]

        with open(log, "a") as lf:
            lf.write(f"\n{'=' * 60}\n")
            lf.write(f"Started at {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
            lf.write(f"Command: {' '.join(cmd)}\n")
            lf.write(f"{'=' * 60}\n\n")
            lf.flush()

            proc = subprocess.Popen(
                cmd,
                stdout=lf,
                stderr=subprocess.STDOUT,
                start_new_session=True,
            )

        pf.write_text(str(proc.pid))
        time.sleep(2)

        if _running_pid():
            print(f"Server started (PID: {proc.pid})")
            print(f"Stop: ag2tracer stop")
        else:
            print(f"Server failed to start. Check logs: {log}")
            sys.exit(1)
    else:
        print(f"Starting ag2tracer...")
        print(f"  URL: http://{host}:{port}")
        print(f"  Press Ctrl+C to stop\n")

        import uvicorn
        from .api import app
        try:
            uvicorn.run(app, host=host, port=port)
        except KeyboardInterrupt:
            print("\nShutting down...")


def stop():
    """Stop the background server."""
    pid = _running_pid()
    if not pid:
        print("Server is not running.")
        return

    print(f"Stopping server (PID: {pid})...")
    try:
        os.kill(pid, signal.SIGTERM)
        for _ in range(10):
            time.sleep(1)
            if not _running_pid():
                print("Server stopped.")
                _pid_file().unlink(missing_ok=True)
                return
        os.kill(pid, signal.SIGKILL)
        time.sleep(1)
        print("Server stopped (forced).")
        _pid_file().unlink(missing_ok=True)
    except ProcessLookupError:
        print("Server process not found.")
        _pid_file().unlink(missing_ok=True)
    except PermissionError:
        print(f"No permission to stop process {pid}.")
        sys.exit(1)


def status():
    """Check server status."""
    pid = _running_pid()
    if pid:
        print(f"Server is running (PID: {pid})")
        return 0
    else:
        print("Server is not running.")
        return 1


def logs(follow: bool = False, lines: int = 50):
    """View server logs."""
    lf = _log_file()
    if not lf.exists():
        print("No log file found.")
        return

    if follow:
        print(f"Following {lf} (Ctrl+C to stop)...")
        try:
            with open(lf) as f:
                f.seek(0, 2)
                while True:
                    line = f.readline()
                    if line:
                        print(line, end="")
                    else:
                        time.sleep(0.1)
        except KeyboardInterrupt:
            print("\nStopped.")
    else:
        with open(lf) as f:
            all_lines = f.readlines()
            for line in all_lines[-lines:]:
                print(line, end="")


def main():
    parser = argparse.ArgumentParser(description="ag2tracer — Failure Attribution on Agentic Traces")
    sub = parser.add_subparsers(dest="command", help="Available commands")

    # launch
    p_launch = sub.add_parser("launch", help="Launch the web interface")
    p_launch.add_argument("--host", default="127.0.0.1", help="Host (default: 127.0.0.1)")
    p_launch.add_argument("--port", type=int, default=8500, help="Port (default: 8500)")
    p_launch.add_argument("--daemon", action="store_true", help="Run in background")

    # stop
    sub.add_parser("stop", help="Stop the background server")

    # status
    sub.add_parser("status", help="Check server status")

    # logs
    p_logs = sub.add_parser("logs", help="View server logs")
    p_logs.add_argument("-f", "--follow", action="store_true", help="Follow log output")
    p_logs.add_argument("-n", "--lines", type=int, default=50, help="Lines to show (default: 50)")

    args = parser.parse_args()

    if args.command == "launch":
        launch(host=args.host, port=args.port, daemon=args.daemon)
    elif args.command == "stop":
        stop()
    elif args.command == "status":
        sys.exit(status())
    elif args.command == "logs":
        logs(follow=args.follow, lines=args.lines)
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
