"""`decisions export` and `decisions replay` (Stream K2; spec §8), registered under the
`decisions` command by `cli_decisions.register`."""

from __future__ import annotations

import argparse
import sys
from datetime import datetime

from app.db import SessionLocal
from app.services.decisions import replay as replay_service
from app.services.decisions.writer import Refused


def cmd_export(args: argparse.Namespace) -> int:
    out = open(args.out, "w", encoding="utf-8") if args.out else sys.stdout
    try:
        with SessionLocal() as db:
            counts = replay_service.export(db, since=datetime.fromisoformat(args.since) if args.since else None, batch_uid=args.batch,
                                           pass_name=args.pass_name, all_=args.all, origin_host=args.origin_host, out=out)
    except Refused as exc:
        print(f"export: {exc.code}: {exc.summary}", file=sys.stderr)
        return 2
    finally:
        if args.out:
            out.close()
    print(f"export: {counts['decisions']} decision(s), {counts['batches']} batch(es), {counts['passes']} pass(es)"
          + (f" -> {args.out}" if args.out else ""), file=sys.stderr)
    return 0


def cmd_replay(args: argparse.Namespace) -> int:
    with SessionLocal() as db:
        try:
            counts = replay_service.replay(db, args.file, check=args.check, label=args.label, force=args.force)
        except Refused as exc:
            print(f"replay: {exc.code}: {exc.summary}")
            return 2
    head = "[check, nothing written] " if args.check else ""
    print(f"{head}replay: {counts['applied']} applied, {counts['already']} already here, {counts['superseded']} superseded on this host, "
          f"{counts['held']} held, {counts['parked']} parked; {counts['batches']} batch(es), {counts['consequences']} consequence(s)")
    for et, per in sorted(counts.get("by_type", {}).items()):
        print(f"  {et}: {per}")
    for item in counts.get("parked_rows", []):
        print(f"  parked {item['uid']} {item['code']}: {item['why']}")
    if counts.get("remainder"):
        print(f"  the remainder is in {counts['remainder']}; a second replay of the same file retries it first")
    return 1 if (counts["parked"] or counts["held"]) else 0


def register_replay(dsub: argparse._SubParsersAction) -> None:
    ex = dsub.add_parser("export", help="JSON lines by natural key, no local id, in (decided_at, id) order")
    ex.add_argument("--since", help="an ISO timestamp")
    ex.add_argument("--batch", help="one batch uid (with every row that reverses or supersedes it)")
    ex.add_argument("--pass", dest="pass_name", help="one pass name")
    ex.add_argument("--all", action="store_true", help="every decision")
    ex.add_argument("--origin-host", help="only rows this host wrote (the refresh passes staging)")
    ex.add_argument("--out", help="the file to write (default stdout)")
    ex.set_defaults(func=cmd_export)

    rp = dsub.add_parser("replay", help="apply an export on this host by natural key; parked rows go to a remainder file")
    rp.add_argument("--file", required=True)
    rp.add_argument("--check", action="store_true", help="run it all in one transaction rolled back; print the counts")
    rp.add_argument("--label", help="the source host, for replayed_from")
    rp.add_argument("--force", action="store_true", help="run even while a collection is running")
    rp.set_defaults(func=cmd_replay)
