#!/usr/bin/env bun
// todo-edit-gate — PreToolUse on Edit|Write|NotebookEdit: deny mutation while no
// task in this session is in_progress. Reads and investigation stay ungated.
// Fails OPEN on any unreadable state: a gate that cannot read the store must
// never wedge a live session.
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { GATE_OFF, gateDisabled, isSidechain, readTasks, tasksDir } from './lib/task-store.mjs';

const CLI = path.join(path.dirname(fileURLToPath(import.meta.url)), 'todo-tasks.mjs');

function deny(reason) {
  console.log(
    JSON.stringify({
      hookSpecificOutput: {
        hookEventName: 'PreToolUse',
        permissionDecision: 'deny',
        permissionDecisionReason: reason,
      },
    })
  );
}

function main() {
  if (gateDisabled()) return;
  let inp = {};
  try {
    inp = JSON.parse(fs.readFileSync(0, 'utf8'));
  } catch {
    return;
  }
  const sessionId = inp.session_id;
  if (!sessionId) return;
  const dir = tasksDir(sessionId);
  if (!fs.existsSync(dir)) return;
  const tasks = readTasks(dir);
  if (!tasks) return;
  const captured = isSidechain(inp.transcript_path)
    ? []
    : tasks.filter((t) => t?.metadata?.autoCaptured === 'true' && t.status === 'pending');
  if (!captured.length && tasks.some((t) => t.status === 'in_progress')) return;

  const open = captured.length
    ? captured
    : tasks.filter((t) => t.status === 'pending' && t?.metadata?.autoCaptured !== 'true');
  const list = open
    .slice(-5)
    .map((t) => `  #${t.id} ${t.subject.slice(0, 80)}`)
    .join('\n');
  const why = captured.length
    ? `${captured.length} auto-captured request(s) from this session are still unclaimed`
    : 'no task is in_progress for this session';
  deny(
    `todo-edit-gate: ${why}, so ${inp.tool_name} is blocked. ` +
      `Reads and investigation are unaffected. Do ONE of these, then retry:\n` +
      `- claim the task this work belongs to: TaskUpdate id=<N> status=in_progress, ` +
      `or from Bash: bun ${CLI} start <N>\n` +
      (open.length ? `${list}\n` : '') +
      `- work with no captured ask: bun ${CLI} new "<what you are doing>"\n` +
      (captured.length ? `- an auto-captured task that needs no work: bun ${CLI} dismiss <N> "<reason>"\n` : '') +
      `Owner escape hatch: touch ${GATE_OFF}`
  );
}

main();
process.exit(0);
