#!/usr/bin/env python3
"""Post the latest weekly review report as a Gitea issue.

⚠️ STANDALONE TOOL — Production flow uses `weekly-retro-runner.sh` + skill,
NOT this script. This script remains for manual / dev / fallback usage:
  - Local testing of the issue create/PATCH flow without claude
  - First-run bootstrap if skill orchestration is broken
  - Manual rebuild of the W-current issue body from refreshed report data

The issue is the actionable artifact for the weekly retro mechanism:
  - title:  "周复盘 YYYY-Www" — ISO-week-only, no rolling date range
  - body:   the report markdown (facts only; candidates added by skill)
  - label:  weekly-retro (created if missing)
  - state:  open until user closes (close = closed loop)

Idempotent by ISO week. If an issue with the same title exists:
  - body has '## 候选改进' section → noop (don't overwrite skill's work)
  - body lacks '## 候选改进' → PATCH body with refreshed facts

Usage:
    python3 scripts/ops/weekly-retro-issue.py                        # latest report
    python3 scripts/ops/weekly-retro-issue.py --report path/to.md
    python3 scripts/ops/weekly-retro-issue.py --dry-run              # don't write

Auth:
    Reads WEEKLY_RETRO_TOKEN, GITEA_API_TOKEN, or GITEA_TOKEN from env (in that order).
    Token needs Gitea PAT scopes: write:repository + write:issue (which
    cover both label management and issue create/PATCH).
"""

from __future__ import annotations

import argparse
import json
import re
import sys
from datetime import datetime
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
from _gitea_api import Api, detect_repo, ensure_label, find_issue_by_title, get_token  # noqa: E402

LABEL_NAME = "weekly-retro"
LABEL_COLOR = "0e8a16"
LABEL_DESC = "周复盘自动生成（weekly-retro skill / Gitea Action workflow）"

REPO_ROOT = Path(__file__).resolve().parents[2]
REPORTS_DIR = REPO_ROOT / "testing" / "reports" / "retros"


def latest_report() -> Path:
    iso = datetime.now().astimezone().isocalendar()
    return REPORTS_DIR / f"{iso.year}-W{iso.week:02d}.md"


def derive_title(report_text: str) -> str:
    """Convert H1 'Weekly Review · 2026-W19 (May 02 – May 09)' → '周复盘 2026-W19'.

    The date range is dropped from the title because it shifts day-by-day with
    the rolling window (e.g., 'May 02 – May 09' on day N vs 'May 03 – May 10'
    on day N+1 of the same ISO week), which breaks idempotency: same-week reruns
    would produce different titles and `find_existing_issue` would create
    duplicate issues. The full date range is still in the report body.
    """
    first = report_text.split("\n", 1)[0]
    h1 = first.lstrip("#").strip()
    title = h1.replace("Weekly Review · ", "周复盘 ").strip()
    return re.sub(r"\s*\(.+\)\s*$", "", title)


def main() -> int:
    p = argparse.ArgumentParser(description="Post weekly review as Gitea issue")
    p.add_argument("--report", help="path to report md (default: latest by ISO week)")
    p.add_argument("--repo", help="owner/repo (default: detect from origin)")
    p.add_argument("--dry-run", action="store_true", help="print plan, don't write")
    args = p.parse_args()

    report_path = Path(args.report) if args.report else latest_report()
    if not report_path.exists():
        print(f"ERROR: report not found: {report_path}", file=sys.stderr)
        return 1

    text = report_path.read_text(encoding="utf-8")
    title = derive_title(text)
    body = text

    repo = args.repo or detect_repo()

    print(f"Repo:   {repo}", file=sys.stderr)
    print(f"Report: {report_path}", file=sys.stderr)
    print(f"Title:  {title}", file=sys.stderr)
    print(f"Body:   {len(body)} chars", file=sys.stderr)

    if args.dry_run:
        print("--- DRY-RUN: no API call made ---")
        print(f"TITLE: {title}")
        print(f"LABEL: {LABEL_NAME}")
        print("---")
        print(body[:500] + ("..." if len(body) > 500 else ""))
        return 0

    api = Api(get_token(extra_env_vars=("WEEKLY_RETRO_TOKEN",)), repo)

    label_id = ensure_label(api, LABEL_NAME, LABEL_COLOR, LABEL_DESC)

    existing = find_issue_by_title(api, LABEL_NAME, title)
    if existing:
        n = existing["number"]
        existing_body = existing.get("body") or ""
        if "## 候选改进" in existing_body:
            print(
                f"Existing issue #{n} ({existing.get('state')}) already has "
                f"'## 候选改进' section — noop to preserve skill-managed body.",
                file=sys.stderr,
            )
            print(f"Noop: {existing.get('html_url')}")
            return 0
        print(f"Existing issue #{n} ({existing.get('state')}); PATCH body (no candidates yet)", file=sys.stderr)
        code, txt = api.patch(f"/issues/{n}", {"body": body})
        if code in (200, 201):
            print(f"Updated: {existing.get('html_url')}")
            return 0
        print(f"ERROR PATCH /issues/{n} → HTTP {code}: {txt[:300]}", file=sys.stderr)
        return 1

    payload = {"title": title, "body": body}
    if label_id is not None:
        payload["labels"] = [label_id]
    code, txt = api.post("/issues", payload)
    if code not in (200, 201):
        print(f"ERROR POST /issues → HTTP {code}: {txt[:300]}", file=sys.stderr)
        return 1
    issue = json.loads(txt)
    print(f"Created: #{issue['number']} {issue.get('html_url')}")
    return 0


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