#!/usr/bin/env python3
"""SRE: triage an alert and close finished investigation threads.

Documented at:
  https://appcd-dev.github.io/stackgen-sdk/code-samples/sre-triage-alerts/

Credentials (flags override env):
  STACKGEN_URL, STACKGEN_TOKEN, STACKGEN_WORKSPACE_ID (or STACKGEN_ORG_ID / STACKGEN_PROJECT)

Usage:

  python examples/sre/triage-alerts.py --dry-run

  python examples/sre/triage-alerts.py --alert-id <uuid> --false-positive

  python examples/sre/triage-alerts.py --alert-id <uuid> --ignore-reason noise --resolve
"""

from __future__ import annotations

import argparse
import json
import os
import sys

from stackgen import StackgenClient, StackgenConfig
from stackgen.errors import StackgenError


def _org_id(cli_value: str | None) -> str:
    return (
        (cli_value or "").strip()
        or os.environ.get("STACKGEN_WORKSPACE_ID", "").strip()
        or os.environ.get("STACKGEN_ORG_ID", "").strip()
        or os.environ.get("STACKGEN_PROJECT", "").strip()
        or os.environ.get("STACKGEN_PROJECT_ID", "").strip()
    )


def _config(args: argparse.Namespace) -> StackgenConfig:
    base = (args.base_url or os.environ.get("STACKGEN_URL", "")).strip()
    token = (args.api_token or os.environ.get("STACKGEN_TOKEN", "")).strip()
    org = _org_id(args.workspace_id)
    if not base or not token:
        raise SystemExit(
            "set --base-url/--api-token or STACKGEN_URL / STACKGEN_TOKEN"
        )
    return StackgenConfig(base_url=base, api_token=token, workspace_id=org)


def _alert_rows(payload: object) -> list[dict]:
    if not isinstance(payload, dict):
        return []
    rows = payload.get("alerts") or payload.get("items") or []
    return [r for r in rows if isinstance(r, dict)]


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--base-url", default="")
    parser.add_argument("--api-token", default="")
    parser.add_argument("--workspace-id",
        "--org-id", default="")
    parser.add_argument("--alert-id", default="")
    parser.add_argument("--q", default="", help="Alert search when --alert-id is omitted")
    parser.add_argument("--ignore-reason", default="")
    parser.add_argument(
        "--false-positive",
        action="store_true",
        help="Set attention to false_positive",
    )
    parser.add_argument(
        "--resolve",
        action="store_true",
        help="Resolve completed/failed/draft investigations for the alert",
    )
    parser.add_argument(
        "--dry-run",
        action="store_true",
        help="List candidates and exit without writing",
    )
    args = parser.parse_args()

    client = StackgenClient(_config(args))
    alert_id = args.alert_id.strip()

    if not alert_id:
        listed = client.sre.list_alerts(status="active", q=args.q or None, page_size=5)
        print("alerts:", json.dumps(listed, indent=2, default=str))
        rows = _alert_rows(listed)
        if rows:
            alert_id = str(rows[0].get("id") or "")

    groups = client.sre.list_investigation_groups(page_size=5)
    print("groups:", json.dumps(groups, indent=2, default=str))

    if args.dry_run:
        if alert_id:
            print(f"alert_id={alert_id}", file=sys.stderr)
        return 0

    if not alert_id:
        print("error: pass --alert-id or ensure list_alerts returns a row", file=sys.stderr)
        return 1

    if args.false_positive:
        updated = client.sre.set_alert_attention(
            alert_id,
            "false_positive",
            reason=args.ignore_reason or None,
        )
        print("attention:", json.dumps(updated, indent=2, default=str))
    elif args.ignore_reason:
        updated = client.sre.ignore_alert(alert_id, reason=args.ignore_reason)
        print("ignored:", json.dumps(updated, indent=2, default=str))
    elif not args.resolve:
        print(
            "pass --false-positive, --ignore-reason TEXT, --resolve, or --dry-run",
            file=sys.stderr,
        )
        return 2

    if args.resolve:
        inv = client.sre.list_investigations(alert_id=alert_id, page_size=50)
        print("investigations:", json.dumps(inv, indent=2, default=str))
        rows: list[dict] = []
        if isinstance(inv, dict):
            rows = [r for r in (inv.get("investigations") or []) if isinstance(r, dict)]
        done = [
            str(r["id"])
            for r in rows
            if r.get("id")
            and str(r.get("status") or "") in {"completed", "failed", "draft"}
        ]
        if done:
            resolved = client.sre.resolve_investigations(done)
            print("resolved:", json.dumps(resolved, indent=2, default=str))
        else:
            print("resolve: no completed/failed/draft threads", file=sys.stderr)

    return 0


if __name__ == "__main__":
    try:
        raise SystemExit(main())
    except StackgenError as exc:
        print(f"error: {exc}", file=sys.stderr)
        if "401" in str(exc) or "missing identity" in str(exc).lower():
            print(
                "hint: SRE /app/sre routes need the edge to inject workspace "
                "identity (X-Appcd-Org).",
                file=sys.stderr,
            )
        raise SystemExit(1)
