import { mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { spawnSync } from 'node:child_process';
import { createHash } from 'node:crypto';
import { tmpdir } from 'node:os';

const readInput = () => {
  try {
    const rawInput = readFileSync(0, 'utf8').trim();
    return rawInput ? JSON.parse(rawInput) : {};
  } catch {
    return {};
  }
};

const runGit = (args) => {
  const result = spawnSync('git', args, { encoding: 'utf8' });
  return result.status === 0 ? result.stdout.split('\n').filter(Boolean) : [];
};

const getStatePath = (input) => {
  const turnId = String(input.turn_id ?? 'unknown').replace(/[^a-zA-Z0-9_.-]/g, '_');
  const cwdHash = createHash('sha256').update(process.cwd()).digest('hex').slice(0, 16);
  return join(tmpdir(), 'codex-fastboard-hooks', cwdHash, `${turnId}.json`);
};

const isTypeScriptSource = (file) => /^src\/.+\.tsx?$/.test(file);

const getDirtyTypeScriptFiles = () => {
  const files = [
    ...runGit(['diff', '--name-only', '--diff-filter=ACMR']),
    ...runGit(['diff', '--cached', '--name-only', '--diff-filter=ACMR']),
    ...runGit(['ls-files', '--others', '--exclude-standard']),
  ];

  return [...new Set(files)].filter(isTypeScriptSource).sort();
};

const getFileState = (file) => {
  try {
    const stat = statSync(file);
    return { mtimeMs: stat.mtimeMs, size: stat.size };
  } catch {
    return null;
  }
};

const input = readInput();
const statePath = getStatePath(input);
const snapshot = Object.fromEntries(
  getDirtyTypeScriptFiles().map((file) => [file, getFileState(file)]),
);

mkdirSync(dirname(statePath), { recursive: true });
writeFileSync(statePath, JSON.stringify(snapshot, null, 2));
