// Shared structured-progress contract for the Activity feature.
//
// Any capability that wants live progress bars / phase chips (instead of the UI regexing prose) appends
// NDJSON lines of this shape to its output/log file, alongside whatever human text it already writes:
//
//   {"job":"dearly-devoted","cap":"split-audiobook","phase":"transcription","status":"running","pct":9,"detail":"0:50:00 / 9:28:24","ts":1730000000000}
//   {"job":"dearly-devoted","cap":"split-audiobook","phase":"verdict","status":"complete","verdict":"CLEAN","chapters":31,"pieces":52,"ts":...}
//
// The parser is deliberately tolerant: a line is treated as structured progress iff it JSON-parses to
// an object carrying a `phase` or `status`; everything else is passed through as a raw log line. So a
// capability can dual-write (human lines + NDJSON) and both render correctly.

export type ProgressLine = {
  job?: string;
  cap?: string;
  phase?: string;
  status?: 'running' | 'complete' | 'failed' | string;
  pct?: number;
  detail?: string;
  ts?: number;
  [k: string]: unknown;
};

export type TailEvent = { kind: 'progress'; progress: ProgressLine } | { kind: 'line'; text: string };

export function parseTailLine(line: string): TailEvent {
  const trimmed = line.trim();
  if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
    try {
      const obj = JSON.parse(trimmed) as Record<string, unknown>;
      if (obj && (typeof obj.phase === 'string' || typeof obj.status === 'string')) {
        return { kind: 'progress', progress: obj as ProgressLine };
      }
    } catch {
      /* not JSON → fall through to raw line */
    }
  }
  return { kind: 'line', text: line };
}
