#!/usr/bin/env bun
// todo-tasks — Bash-runnable control surface for the session task store, so an
// agent without the TaskCreate/TaskUpdate tools (every subagent) can satisfy the
// TODO gates. Session id comes from --session, $CLAUDE_SESSION_ID, or the newest
// task dir that holds an auto-capture ledger.
import fs from 'node:fs';
import path from 'node:path';
import {
  appendLedger,
  createTask,
  ledgerPath,
  readLedger,
  readTask,
  readTasks,
  tasksDir,
  writeTask,
} from './lib/task-store.mjs';

const HOME = process.env.HOME || '/home/user';

function resolveSession(explicit) {
  if (explicit) return explicit;
  if (process.env.CLAUDE_SESSION_ID) return process.env.CLAUDE_SESSION_ID;
  const root = path.join(HOME, '.claude', 'tasks');
  let best = null;
  for (const n of fs.readdirSync(root)) {
    const d = path.join(root, n);
    let st;
    try {
      st = fs.statSync(ledgerPath(d));
    } catch {
      continue;
    }
    if (!best || st.mtimeMs > best.mtime) best = { id: n, mtime: st.mtimeMs };
  }
  if (!best) throw new Error('cannot resolve session id — pass --session <id>');
  return best.id;
}

function dismissCount(dir) {
  return readLedger(dir).filter((e) => e.event === 'dismiss').length;
}

function fmt(t) {
  return `#${t.id} [${t.status}] ${t.subject}`;
}

function main() {
  const argv = process.argv.slice(2);
  let session = null;
  const i = argv.indexOf('--session');
  if (i >= 0) {
    session = argv[i + 1];
    argv.splice(i, 2);
  }
  const cmd = argv[0];
  if (!cmd || cmd === '--help' || cmd === 'help') {
    console.log(
      [
        'todo-tasks <command> [--session <id>]',
        '  list                       show this session\'s open tasks + dismissal count',
        '  new "<subject>" [desc]     create a task and set it in_progress',
        '  start <id>                 set a task in_progress (releases the edit gate)',
        '  done <id>                  set a task completed',
        '  dismiss <id> "<reason>"    close an auto-captured task that needs no work',
      ].join('\n')
    );
    return 0;
  }

  const dir = tasksDir(resolveSession(session));

  if (cmd === 'list') {
    const tasks = readTasks(dir) || [];
    const open = tasks.filter((t) => t.status !== 'completed');
    for (const t of open) console.log(fmt(t));
    console.log(
      `-- ${open.length} open, ${tasks.length} total, ${dismissCount(dir)} dismissed (session ${path.basename(dir)})`
    );
    return 0;
  }

  if (cmd === 'new') {
    const subject = argv[1];
    if (!subject) throw new Error('new: subject required');
    const t = createTask(dir, {
      subject: subject.slice(0, 120),
      description: argv[2] || subject,
      activeForm: `Working on: ${subject.slice(0, 80)}`,
      metadata: { createdBy: 'todo-tasks' },
    });
    t.status = 'in_progress';
    writeTask(dir, t);
    console.log(`created and started ${fmt(t)}`);
    return 0;
  }

  const id = argv[1];
  if (!id) throw new Error(`${cmd}: task id required`);
  const t = readTask(dir, id);
  if (!t) throw new Error(`task #${id} not found in ${dir}`);

  if (cmd === 'start') {
    t.status = 'in_progress';
    writeTask(dir, t);
    console.log(`started ${fmt(t)}`);
    return 0;
  }
  if (cmd === 'done') {
    t.status = 'completed';
    writeTask(dir, t);
    console.log(`completed ${fmt(t)}`);
    return 0;
  }
  if (cmd === 'dismiss') {
    const reason = argv.slice(2).join(' ').trim();
    if (!reason) throw new Error('dismiss: a reason is required');
    t.status = 'completed';
    if (!t.subject.startsWith('[dismissed] ')) t.subject = `[dismissed] ${t.subject}`;
    t.metadata = { ...(t.metadata || {}), dismissedAt: new Date().toISOString(), dismissedReason: reason };
    writeTask(dir, t);
    appendLedger(dir, { event: 'dismiss', id: t.id, reason, at: new Date().toISOString() });
    console.log(`dismissed ${fmt(t)} — ${reason}`);
    console.log(`-- dismissals this session: ${dismissCount(dir)}`);
    return 0;
  }
  throw new Error(`unknown command: ${cmd}`);
}

try {
  process.exit(main());
} catch (e) {
  console.error(`todo-tasks: ${e.message}`);
  process.exit(1);
}
