import argparse
import json
import os
import uuid
from datetime import datetime, timezone
from pathlib import Path


DEFAULT_AUTOMATION_DIR = ".prd_plugin/local/automation"
DEFAULT_STALE_AFTER_SECONDS = 900


def _now():
    return datetime.now(timezone.utc)


def _iso(value):
    return value.astimezone(timezone.utc).isoformat().replace("+00:00", "Z")


def _parse_time(value):
    return datetime.fromisoformat(str(value).replace("Z", "+00:00"))


def _read_json(path):
    return json.loads(Path(path).read_text(encoding="utf-8"))


def _write_json(path, data):
    path = Path(path)
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")


def _lock_path(automation_dir, name):
    return Path(automation_dir) / f"{name}.lock.json"


def _pending_path(automation_dir, name):
    return Path(automation_dir) / f"{name}.pending.json"


def _is_stale(lock, now, stale_after_seconds):
    updated_at = lock.get("updated_at") or lock.get("started_at")
    if not updated_at:
        return True
    age = (now - _parse_time(updated_at)).total_seconds()
    return age > stale_after_seconds


def _mark_pending(path, lock, now):
    pending = {}
    if path.exists():
        pending = _read_json(path)
    pending["pending_count"] = int(pending.get("pending_count", 0)) + 1
    pending["requested_at"] = _iso(now)
    pending["waiting_for_run_id"] = lock.get("run_id")
    _write_json(path, pending)
    return pending


def begin_run(
    automation_dir=DEFAULT_AUTOMATION_DIR,
    name="request-check",
    run_id=None,
    now=None,
    stale_after_seconds=DEFAULT_STALE_AFTER_SECONDS,
):
    now = now or _now()
    run_id = run_id or f"RUN-{uuid.uuid4()}"
    automation_dir = Path(automation_dir)
    lock_path = _lock_path(automation_dir, name)
    pending_path = _pending_path(automation_dir, name)

    if lock_path.exists():
        lock = _read_json(lock_path)
        if not _is_stale(lock, now, stale_after_seconds):
            pending = _mark_pending(pending_path, lock, now)
            return {
                "status": "busy",
                "run_id": run_id,
                "active_run_id": lock.get("run_id"),
                "pending_count": pending["pending_count"],
                "lock_path": str(lock_path),
                "pending_path": str(pending_path),
            }
        previous_run_id = lock.get("run_id")
        status = "stale_takeover"
    else:
        previous_run_id = None
        status = "started"

    lock = {
        "name": name,
        "run_id": run_id,
        "pid": os.getpid(),
        "started_at": _iso(now),
        "updated_at": _iso(now),
        "stale_after_seconds": stale_after_seconds,
    }
    _write_json(lock_path, lock)
    result = {
        "status": status,
        "run_id": run_id,
        "lock_path": str(lock_path),
        "pending_path": str(pending_path),
    }
    if previous_run_id:
        result["previous_run_id"] = previous_run_id
    return result


def complete_run(
    automation_dir=DEFAULT_AUTOMATION_DIR,
    name="request-check",
    run_id=None,
    now=None,
):
    now = now or _now()
    automation_dir = Path(automation_dir)
    lock_path = _lock_path(automation_dir, name)
    pending_path = _pending_path(automation_dir, name)

    if not lock_path.exists():
        return {"status": "no_lock", "run_id": run_id, "pending_follow_up": False}

    lock = _read_json(lock_path)
    if run_id and lock.get("run_id") != run_id:
        return {
            "status": "not_owner",
            "run_id": run_id,
            "active_run_id": lock.get("run_id"),
            "pending_follow_up": False,
        }

    lock_path.unlink()
    pending = None
    if pending_path.exists():
        pending = _read_json(pending_path)
        pending_path.unlink()

    return {
        "status": "completed",
        "run_id": lock.get("run_id"),
        "completed_at": _iso(now),
        "pending_follow_up": pending is not None,
        "pending_count": int(pending.get("pending_count", 0)) if pending else 0,
    }


def main():
    parser = argparse.ArgumentParser(description="Guard recurring PRD Plugin automation runs.")
    parser.add_argument("command", choices=("begin", "complete"))
    parser.add_argument("--name", default="request-check")
    parser.add_argument("--automation-dir", default=DEFAULT_AUTOMATION_DIR)
    parser.add_argument("--run-id")
    parser.add_argument("--stale-after-seconds", type=int, default=DEFAULT_STALE_AFTER_SECONDS)
    args = parser.parse_args()

    if args.command == "begin":
        result = begin_run(
            args.automation_dir,
            args.name,
            run_id=args.run_id,
            stale_after_seconds=args.stale_after_seconds,
        )
        print(json.dumps(result, indent=2))
        if result["status"] == "busy":
            raise SystemExit(75)
        return

    result = complete_run(args.automation_dir, args.name, run_id=args.run_id)
    print(json.dumps(result, indent=2))
    if result["status"] == "not_owner":
        raise SystemExit(2)


if __name__ == "__main__":
    main()
