"""
Dryft CLI entry. Commands: init, start, stop, status, config, push-notify.
Matches PRD §6.1 and §12.1.
"""

import argparse
import json
import os
import sys
from pathlib import Path

from . import api, config as config_mod
from .init_ import run_init
from . import daemon as daemon_mod


def _cwd(args: argparse.Namespace) -> str:
    return getattr(args, "cwd", None) or os.getcwd()


def cmd_init(args: argparse.Namespace) -> int:
    """Create .dryft/, context.md, intent.md, .gitignore; prompt for server URL and project id."""
    try:
        run_init(_cwd(args))
        return 0
    except SystemExit as e:
        print(e, file=sys.stderr)
        return 1


def cmd_start(args: argparse.Namespace) -> int:
    """Start the background daemon (polling + sync). Use --foreground to run in terminal."""
    try:
        daemon_mod.start_daemon(
            cwd=_cwd(args),
            foreground=getattr(args, "foreground", False),
        )
        return 0
    except SystemExit as e:
        print(e, file=sys.stderr)
        return 1


def cmd_stop(args: argparse.Namespace) -> int:
    """Stop the daemon."""
    daemon_mod.stop_daemon(_cwd(args))
    return 0


def cmd_status(args: argparse.Namespace) -> int:
    """Show current sync status and any warnings."""
    cwd = _cwd(args)
    cfg = config_mod.load_config(cwd)
    if not cfg:
        print("Run dryft init first.", file=sys.stderr)
        return 1
    last_sync_path = Path(cwd) / ".dryft" / "last_sync.json"
    try:
        data = json.loads(last_sync_path.read_text(encoding="utf-8"))
        if data.get("last_sync"):
            print("Last sync:", data["last_sync"])
        if data.get("error"):
            print("Last error:", data["error"])
    except (OSError, json.JSONDecodeError):
        print("No sync recorded yet. Run dryft start to sync.")
    try:
        state = api.get_context(cfg["server_url"], cfg["project_id"])
        devs = state.get("developers") or {}
        others = [k for k in devs if k != cfg["developer_id"]]
        if devs:
            print("Other developers:", ", ".join(others) or "none")
        warnings = state.get("warnings") or []
        if warnings:
            print("Warnings:", len(warnings))
            for w in warnings:
                print(" -", w.get("detail") or f"{w.get('file', '?')}: {', '.join(w.get('developers') or [])}")
    except Exception as e:
        print("Could not fetch server state:", e)
    return 0


def cmd_config(args: argparse.Namespace) -> int:
    """View or edit configuration (server URL, developer id, poll interval)."""
    cwd = _cwd(args)
    cfg = config_mod.load_config(cwd)
    if not cfg:
        print("Run dryft init first.", file=sys.stderr)
        return 1
    sub = getattr(args, "config_args", []) or []  # e.g. ["set", "server_url", "http://..."]
    if len(sub) >= 3 and sub[0] == "set" and sub[1] and sub[2] is not None:
        key, value = sub[1], sub[2]
        next_cfg = dict(cfg)
        if key == "server_url":
            next_cfg["server_url"] = value.rstrip("/")
        elif key == "project_id":
            next_cfg["project_id"] = value
        elif key == "developer_id":
            next_cfg["developer_id"] = value
        elif key == "poll_interval_ms":
            next_cfg["poll_interval_ms"] = int(value) or cfg.get("poll_interval_ms") or 60_000
        else:
            print("Unknown key. Use: server_url, project_id, developer_id, poll_interval_ms", file=sys.stderr)
            return 1
        config_mod.save_config(cwd, next_cfg)
        print("Config updated.")
        return 0
    print("server_url:", cfg["server_url"])
    print("project_id:", cfg["project_id"])
    print("developer_id:", cfg["developer_id"])
    print("poll_interval_ms:", cfg.get("poll_interval_ms") or 60_000)
    return 0


def cmd_push_notify(args: argparse.Namespace) -> int:
    """Manually notify the other developer that you've pushed."""
    cwd = _cwd(args)
    cfg = config_mod.load_config(cwd)
    if not cfg:
        print("Run dryft init first.", file=sys.stderr)
        return 1
    try:
        api.post_push_notify(
            cfg["server_url"],
            {"developer": cfg["developer_id"], "project_id": cfg["project_id"]},
        )
        print("Push notification sent.")
        return 0
    except Exception as e:
        print("Push notify failed:", e, file=sys.stderr)
        return 1


def cmd_update(_args: argparse.Namespace) -> int:
    """Upgrade Dryft client to the latest version (pip install --upgrade dryft)."""
    import subprocess
    print("Upgrading Dryft client to latest version...")
    try:
        code = subprocess.run(
            [sys.executable, "-m", "pip", "install", "--upgrade", "dryft"],
            check=False,
        ).returncode
        if code != 0:
            print("Update failed. You can try manually: pip install --upgrade dryft", file=sys.stderr)
            return 1
        print("Dryft updated. Run 'dryft --help' to see commands.")
        return 0
    except FileNotFoundError:
        print("Could not find pip. Try: pip install --upgrade dryft", file=sys.stderr)
        return 1


def print_help(_args: argparse.Namespace) -> int:
    """Print usage."""
    help_text = """Dryft CLI (Stage 1)
Usage: dryft <command>

Commands:
  init         Initialize Dryft in the current repo
  start       Start the background daemon
  stop        Stop the daemon
  status      Show sync status and warnings
  config      View or edit config (server URL, developer id, poll interval)
  push-notify Notify the other developer that you've pushed
  update      Upgrade Dryft client to the latest version (pip install --upgrade dryft)

Install: pip install dryft  (or npm install -g dryft for Node client)
See REPO_STRUCTURE.md and the PRD for full details.
"""
    print(help_text)
    return 0


def main() -> int:
    parser = argparse.ArgumentParser(prog="dryft", description="Dryft — agent context sync")
    parser.add_argument("--cwd", default=None, help="Working directory (default: current)")
    subparsers = parser.add_subparsers(dest="command", help="Command")

    for name, fn in [
        ("init", cmd_init),
        ("start", cmd_start),
        ("stop", cmd_stop),
        ("status", cmd_status),
        ("config", cmd_config),
        ("push-notify", cmd_push_notify),
        ("update", cmd_update),
    ]:
        sub = subparsers.add_parser(name)
        sub.set_defaults(func=fn)
        if name == "start":
            sub.add_argument("--foreground", action="store_true", help="Run daemon in foreground")
        elif name == "config":
            sub.add_argument("config_args", nargs="*", help="get | set key value")

    args = parser.parse_args()
    if getattr(args, "func", None) is None:
        return print_help(args)
    return args.func(args)


if __name__ == "__main__":
    sys.exit(main())
