"""finish-task timing logger: JSONL append per stage. Schema: {ts, task_id, stage, status, duration_ms, meta}."""
from __future__ import annotations

import json
import os
from datetime import datetime, timezone
from pathlib import Path


class Stage:
    """18 stage constants for finish-task lifecycle timing."""

    INIT = "INIT"
    CANCEL_CHECK = "CANCEL_CHECK"
    QC_START = "QC_START"
    QC_VALIDATE = "QC_VALIDATE"
    QC_DONE = "QC_DONE"
    GIT_PRECHECK = "GIT_PRECHECK"
    GIT_MERGE_PREP = "GIT_MERGE_PREP"
    GIT_MERGE = "GIT_MERGE"
    GIT_PUSH = "GIT_PUSH"
    DONE_MARKER = "DONE_MARKER"
    TIMER_END = "TIMER_END"
    NOTIFY_DISPATCH = "NOTIFY_DISPATCH"
    NOTIFY_COMPLETE = "NOTIFY_COMPLETE"
    ANU_CALLBACK_REGISTER = "ANU_CALLBACK_REGISTER"
    ANU_CALLBACK_FIRE = "ANU_CALLBACK_FIRE"
    CHAIN_NEXT = "CHAIN_NEXT"
    CLEANUP = "CLEANUP"
    FINALIZE = "FINALIZE"


ALL_STAGES = (
    Stage.INIT, Stage.CANCEL_CHECK, Stage.QC_START, Stage.QC_VALIDATE, Stage.QC_DONE,
    Stage.GIT_PRECHECK, Stage.GIT_MERGE_PREP, Stage.GIT_MERGE, Stage.GIT_PUSH,
    Stage.DONE_MARKER, Stage.TIMER_END, Stage.NOTIFY_DISPATCH, Stage.NOTIFY_COMPLETE,
    Stage.ANU_CALLBACK_REGISTER, Stage.ANU_CALLBACK_FIRE, Stage.CHAIN_NEXT,
    Stage.CLEANUP, Stage.FINALIZE,
)

_LOG_PATH = Path("memory/logs/finish-task-timing.jsonl")


def log_stage(task_id: str, stage: str, status: str, duration_ms: int | None = None, meta: dict | None = None) -> None:
    """Append one JSONL record for a finish-task stage with UTC timestamp and fsync."""
    record = {
        "ts": datetime.now(timezone.utc).isoformat(),
        "task_id": task_id,
        "stage": stage,
        "status": status,
        "duration_ms": duration_ms,
        "meta": meta or {},
    }
    _LOG_PATH.parent.mkdir(parents=True, exist_ok=True)
    line = json.dumps(record, ensure_ascii=False, separators=(",", ":")) + "\n"
    with open(_LOG_PATH, "a", encoding="utf-8") as f:
        f.write(line)
        f.flush()
        try:
            os.fsync(f.fileno())
        except OSError:
            pass
