"""Trace lifecycle ops handlers extracted from `hiveos.observe`."""

from __future__ import annotations

import json

from hiveos_trace import terminal_style as _term


def handle_trace_archive(args, *, archive_run_record):
    run_id = str(args.run_id or "").strip()
    if not run_id:
        raise SystemExit("run_id is required")
    record = archive_run_record(run_id, archive=True, reason=args.reason, actor=args.actor)
    if not record:
        raise SystemExit(f"run_id not found: {run_id}")
    print(f"{_term.key('archived')}={run_id}")
    return 0


def handle_trace_unarchive(args, *, archive_run_record):
    run_id = str(args.run_id or "").strip()
    if not run_id:
        raise SystemExit("run_id is required")
    record = archive_run_record(run_id, archive=False)
    if not record:
        raise SystemExit(f"run_id not found: {run_id}")
    print(f"{_term.key('unarchived')}={run_id}")
    return 0


def handle_trace_prune(
    args,
    *,
    parse_age_window_ms,
    now_ms_fn,
    list_all_run_records,
    record_is_archived,
    record_reference_time_ms,
    run_file,
    drop_events_for_runs,
):
    try:
        window_ms = parse_age_window_ms(args.older_than)
    except ValueError as exc:
        raise SystemExit(str(exc))
    now = now_ms_fn()
    cutoff = now - window_ms
    all_records = list_all_run_records()
    candidates = []
    for record in all_records:
        if not bool(args.include_active) and not record_is_archived(record):
            continue
        ref_ms = record_reference_time_ms(record)
        if ref_ms <= 0:
            continue
        if ref_ms <= cutoff:
            candidates.append(record)
    if not candidates:
        print(f"{_term.key('pruned_runs')}=0 {_term.key('dropped_events')}=0")
        return 0

    run_ids_by_log = {}
    removed = 0
    for record in candidates:
        run_id = str(record.get("run_id") or "").strip()
        if not run_id:
            continue
        try:
            run_file(run_id).unlink(missing_ok=True)
            removed += 1
        except Exception:
            continue
        trace_log = str(record.get("trace_log_path") or "").strip()
        if trace_log:
            run_ids_by_log.setdefault(trace_log, set()).add(run_id)
    dropped = {"dropped_events": 0, "touched_files": 0}
    if bool(args.drop_events):
        dropped = drop_events_for_runs(run_ids_by_log)
    print(
        f"{_term.key('pruned_runs')}={removed} {_term.key('dropped_events')}={int(dropped['dropped_events'])} "
        f"{_term.key('touched_files')}={int(dropped['touched_files'])}"
    )
    return 0


def handle_trace_reconcile(
    args,
    *,
    config_module,
    parse_duration_window_ms,
    reconcile_stale_running_runs,
):
    if not bool(getattr(config_module, "TRACE_RECONCILE_ENABLED", True)):
        summary = {
            "checked_running": 0,
            "reconciled_runs": 0,
            "reconciled_run_ids": [],
            "stale_after_ms": 0,
            "enabled": False,
        }
        if args.json:
            print(json.dumps(summary, separators=(",", ":")))
        else:
            print(_term.warn("reconcile disabled by config"))
        return 0
    stale_raw = str(args.stale_after or "").strip()
    if stale_raw:
        try:
            stale_ms = parse_duration_window_ms(stale_raw, default_unit="s")
        except ValueError as exc:
            raise SystemExit(str(exc))
    else:
        stale_sec = int(getattr(config_module, "TRACE_RECONCILE_STALE_SEC", 300) or 300)
        stale_ms = max(1, stale_sec) * 1000
    summary = reconcile_stale_running_runs(stale_after_ms=stale_ms, emit_events=True)
    summary["enabled"] = True
    if args.json:
        print(json.dumps(summary, separators=(",", ":")))
    else:
        print(_term.section("reconcile"))
        print(
            f"  {_term.key('checked_running')}={summary['checked_running']} "
            f"{_term.key('reconciled_runs')}={summary['reconciled_runs']} "
            f"{_term.key('stale_after_ms')}={summary['stale_after_ms']}"
        )
        if summary["reconciled_run_ids"]:
            print(_term.section("reconciled_run_ids"))
            for run_id in summary["reconciled_run_ids"]:
                print(f"  {run_id}")
    return 0
