#!/usr/bin/env python3
"""
KAR-72 Part 3: scan Linear KAR-issues, surface stale Backlog items for prune-review.

Output: /tmp/aria-prune-YYYY-MM-DD.json with candidates.

Stale-criteria (default):
  - state in {Backlog, Todo}
  - age >= 30 days since createdAt
  - no comments/updates in last 14 days (proxy: updatedAt <= 14d ago)

Aria reads this, runs Multi-Level-Challenge per candidate (reverse:
"is this still relevant?"), proposes batch to Kais via Telegram.

Requires LINEAR_API_KEY in /root/aria/.env.
"""
from __future__ import annotations

import argparse
import json
import os
import sys
from datetime import datetime, timedelta, timezone
from pathlib import Path
from urllib import request as urlrequest

API = "https://api.linear.app/graphql"
QUERY = """
query StaleIssues($teamKey: String!) {
  issues(
    filter: {
      team: { key: { eq: $teamKey } }
      state: { type: { in: ["backlog", "started", "unstarted"] } }
    }
    orderBy: updatedAt
    first: 100
  ) {
    nodes {
      identifier
      title
      priority
      priorityLabel
      url
      createdAt
      updatedAt
      state { name type }
      labels(first: 5) { nodes { name } }
      comments(first: 1) { nodes { createdAt } }
    }
  }
}
"""


def load_env(path: str = "/root/aria/.env") -> dict:
    env: dict = {}
    p = Path(path)
    if not p.exists():
        return env
    for line in p.read_text().splitlines():
        line = line.strip()
        if not line or line.startswith("#") or "=" not in line:
            continue
        k, _, v = line.partition("=")
        env[k.strip()] = v.strip().strip("'").strip('"')
    return env


def post_graphql(token: str, query: str, variables: dict) -> dict:
    body = json.dumps({"query": query, "variables": variables}).encode()
    req = urlrequest.Request(
        API,
        data=body,
        headers={
            "Content-Type": "application/json",
            "Authorization": token,
        },
    )
    with urlrequest.urlopen(req, timeout=30) as resp:
        data = json.load(resp)
    if data.get("errors"):
        raise RuntimeError(f"GraphQL errors: {data['errors']}")
    return data["data"]


def age_days(iso_ts: str) -> int:
    dt = datetime.fromisoformat(iso_ts.replace("Z", "+00:00"))
    return (datetime.now(timezone.utc) - dt).days


def main():
    parser = argparse.ArgumentParser(
        description="KAR-72: scan Linear stale Backlog issues for prune review"
    )
    parser.add_argument(
        "--team-key", default="KAR", help="Linear team key (default: KAR)"
    )
    parser.add_argument(
        "--min-age-days",
        type=int,
        default=30,
        help="Minimum age to consider stale (default: 30)",
    )
    parser.add_argument(
        "--min-staleness-days",
        type=int,
        default=14,
        help="Days since last update to consider stale (default: 14)",
    )
    parser.add_argument(
        "--out",
        default=f"/tmp/aria-prune-{datetime.now().strftime('%Y-%m-%d')}.json",
    )
    parser.add_argument("--print", action="store_true")
    args = parser.parse_args()

    env = load_env()
    token = env.get("LINEAR_API_KEY") or os.environ.get("LINEAR_API_KEY")
    if not token:
        print("Missing LINEAR_API_KEY in /root/aria/.env or env", file=sys.stderr)
        sys.exit(2)

    data = post_graphql(token, QUERY, {"teamKey": args.team_key})
    issues = data.get("issues", {}).get("nodes", [])
    if not issues:
        print(f"no issues found for team {args.team_key}", file=sys.stderr)
    now = datetime.now(timezone.utc)

    candidates: list[dict] = []
    for iss in issues:
        age = age_days(iss["createdAt"])
        last_update = age_days(iss["updatedAt"])
        if age < args.min_age_days:
            continue
        if last_update < args.min_staleness_days:
            continue
        candidates.append(
            {
                "id": iss["identifier"],
                "title": iss["title"],
                "url": iss["url"],
                "state": iss["state"]["name"],
                "priority": iss["priorityLabel"],
                "age_days": age,
                "stale_days": last_update,
                "labels": [l["name"] for l in iss["labels"]["nodes"]],
                "has_recent_comments": bool(iss["comments"]["nodes"]),
            }
        )

    payload = {
        "generated_at": now.isoformat(),
        "team_key": args.team_key,
        "min_age_days": args.min_age_days,
        "min_staleness_days": args.min_staleness_days,
        "candidate_count": len(candidates),
        "candidates": candidates,
    }
    out = Path(args.out)
    out.write_text(json.dumps(payload, ensure_ascii=False, indent=2))
    print(f"{len(candidates)} stale candidates -> {out}")

    if args.print:
        for c in candidates:
            print(
                f"  {c['id']:8s}  {c['state']:14s}  {c['age_days']:3d}d old  "
                f"({c['stale_days']:3d}d stale)  {c['title'][:60]}"
            )


if __name__ == "__main__":
    main()
