"""`app.cli pass packet | status | fingerprint | parked | unpark`: what a review pass is given, and
how the review knows it is done (Stream K12.5; `docs/REVIEW-PASS.md`)."""

from __future__ import annotations

import argparse
import json
import sys

from app.db import SessionLocal
from app.services import pass_packet, proposals
from app.services.decisions.writer import Refused


def cmd_packet(args: argparse.Namespace) -> int:
    with SessionLocal() as db:
        try:
            out = pass_packet.packet(db, args.brand, layer=args.layer)
        except ValueError as exc:
            print(str(exc), file=sys.stderr)
            return 1
    print(json.dumps(out, indent=None if args.compact else 1, ensure_ascii=False, default=str))
    return 0


def cmd_status(args: argparse.Namespace) -> int:
    with SessionLocal() as db:
        try:
            out = pass_packet.status(db, args.brand)
        except ValueError as exc:
            print(str(exc), file=sys.stderr)
            return 1
    if args.json:
        print(json.dumps(out, indent=1, default=str))
        return 0
    for b in out["brands"]:
        if args.brand or b["state"] != "settled" or args.all:
            print(f"  {b['brand_slug']:32s} {b['state']:10s} layer={b['layer'] or '-':16s} {b['why']}")
    if out.get("line"):
        print(out["line"])
    return 0 if out.get("done") or args.brand else 3


def cmd_fingerprint(args: argparse.Namespace) -> int:
    with SessionLocal() as db:
        brand, family = pass_packet._family(db, args.brand)
        if brand is None:
            print(f"no brand {args.brand!r}", file=sys.stderr)
            return 1
        print(pass_packet.fingerprint(db, [b.id for b in family]))
    return 0


def cmd_parked(args: argparse.Namespace) -> int:
    with SessionLocal() as db:
        rows = proposals.parked_questions(db, args.brand)
    if args.json:
        print(json.dumps(rows, indent=1))
        return 0
    if not rows:
        print("nothing parked")
    for r in rows:
        print(f"{r['uid']}  {r['brand_slug']}  {r['field']}  {r['natural_key']}\n    {r['question']}\n    notes: " + " | ".join(r["notes"]))
        print(f"    running list: python3 main/scripts/items.py add --kind decide --by review --title \"{(r['question'] or '')[:80]}\" "
              f"--detail \"parked from the review; answer, then app.cli pass unpark {r['uid']} --note '<the answer>' --by rian\"")
    return 0


def cmd_unpark(args: argparse.Namespace) -> int:
    with SessionLocal() as db:
        try:
            out = proposals.unpark(db, args.uid, note=args.note, by=args.by)
        except Refused as exc:
            print(f"unpark refused: {exc.code}: {exc.summary}", file=sys.stderr)
            return 2
    print(f"{out['uid']} is {out['status']} with the answer as its note; the next pass reads it")
    return 0


def register(sub) -> None:
    p = sub.add_parser("pass", help="a review pass's packet, the settled state per brand, the one done line (K12)")
    ps = p.add_subparsers(dest="pass_command", required=True)
    pk = ps.add_parser("packet", help="everything a pass may know about one brand, as one JSON document")
    pk.add_argument("--brand", required=True)
    pk.add_argument("--layer", choices=list(pass_packet.LAYERS), help="the layer to work; default: the outermost with open questions")
    pk.add_argument("--compact", action="store_true")
    pk.set_defaults(func=cmd_packet)
    st = ps.add_parser("status", help="per brand: parked | open | deferred | settled | unsettled | never; and the done line (exit 3 until done)")
    st.add_argument("--brand")
    st.add_argument("--all", action="store_true", help="list settled brands too")
    st.add_argument("--json", action="store_true")
    st.set_defaults(func=cmd_status)
    fp = ps.add_parser("fingerprint", help="the brand family's listed-words fingerprint a settled pass stamps")
    fp.add_argument("--brand", required=True)
    fp.set_defaults(func=cmd_fingerprint)
    pd = ps.add_parser("parked", help="questions parked to rian, with the running-list command for each")
    pd.add_argument("--brand")
    pd.add_argument("--json", action="store_true")
    pd.set_defaults(func=cmd_parked)
    up = ps.add_parser("unpark", help="rian answered a parked question: it becomes a deferral carrying his answer")
    up.add_argument("uid")
    up.add_argument("--note", required=True)
    up.add_argument("--by", required=True)
    up.set_defaults(func=cmd_unpark)
