// engine/db/migrations/003-work-items.js
//
// Phase 2: move work-items.json (central + per-project) into a `work_items`
// table.
//
// Same hybrid schema as `dispatches`: typed projection columns for hot
// filters (scope/status/agent/parent), plus a `data` TEXT column holding
// the full record JSON so future fields land transparently.
//
// `scope` keys the file the record came from: 'central' for
// <MINIONS_DIR>/work-items.json, otherwise the project name (matches the
// directory under projects/<name>/). Per-scope writes diff against the
// scope's rows so a mutation on one project's file never touches another's.
//
// Backfill: walk central + every projects/<name>/work-items.json. The
// JSON files stay on disk as a dual-write mirror so legacy direct-readers
// continue to function while we migrate them in Phase 2.5.

const path = require('path');
const fs = require('fs');

function _resolveMinionsDir() {
  const envHome = process.env.MINIONS_TEST_DIR || process.env.MINIONS_HOME;
  if (envHome) return envHome;
  try { return require('../../shared').MINIONS_DIR; } catch { return null; }
}

function _toMs(v) {
  if (v == null) return null;
  if (typeof v === 'number') return Number.isFinite(v) ? v : null;
  const parsed = Date.parse(v);
  return Number.isFinite(parsed) ? parsed : null;
}

function _readJsonArray(filePath) {
  try {
    const raw = fs.readFileSync(filePath, 'utf8');
    const parsed = JSON.parse(raw);
    return Array.isArray(parsed) ? parsed : [];
  } catch {
    return [];
  }
}

function _listProjectDirs(minionsDir) {
  const projectsRoot = path.join(minionsDir, 'projects');
  let entries;
  try { entries = fs.readdirSync(projectsRoot, { withFileTypes: true }); }
  catch { return []; }
  const out = [];
  for (const e of entries) {
    if (!e.isDirectory()) continue;
    if (e.name === '.archived') continue;
    out.push(e.name);
  }
  return out;
}

module.exports = {
  version: 3,
  description: 'work_items: schema + work-items.json backfill (central + per-project)',
  up(db) {
    db.exec(`
      CREATE TABLE work_items (
        id            TEXT NOT NULL,
        scope         TEXT NOT NULL,
        status        TEXT NOT NULL,
        type          TEXT,
        agent         TEXT,
        parent_id     TEXT,
        created_at    INTEGER,
        completed_at  INTEGER,
        data          TEXT NOT NULL,
        updated_at    INTEGER NOT NULL,
        PRIMARY KEY (scope, id)
      );
      CREATE INDEX idx_wi_status        ON work_items(status);
      CREATE INDEX idx_wi_scope_status  ON work_items(scope, status);
      CREATE INDEX idx_wi_agent         ON work_items(agent);
      CREATE INDEX idx_wi_parent        ON work_items(parent_id);
    `);

    const minionsDir = _resolveMinionsDir();
    if (!minionsDir) return;

    const insert = db.prepare(`
      INSERT INTO work_items (id, scope, status, type, agent, parent_id, created_at, completed_at, data, updated_at)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `);

    const now = Date.now();
    let inserted = 0;

    const backfillFile = (scope, filePath) => {
      const rows = _readJsonArray(filePath);
      for (const wi of rows) {
        if (!wi || typeof wi !== 'object' || !wi.id) continue;
        try {
          insert.run(
            String(wi.id),
            scope,
            String(wi.status || 'pending'),
            wi.type || null,
            wi.dispatched_to || wi.agent || null,
            wi.parent_id || null,
            _toMs(wi.created_at),
            _toMs(wi.completed_at || wi.completedAt),
            JSON.stringify(wi),
            now,
          );
          inserted += 1;
        } catch {
          // Duplicate (scope, id) within the same file → skip. Real-world
          // work-items.json doesn't carry dupes, but defensive: a corrupted
          // file shouldn't abort the whole migration.
        }
      }
    };

    backfillFile('central', path.join(minionsDir, 'work-items.json'));
    for (const projectName of _listProjectDirs(minionsDir)) {
      backfillFile(projectName, path.join(minionsDir, 'projects', projectName, 'work-items.json'));
    }

    // eslint-disable-next-line no-console
    console.log(`[db-migrate] v3: backfilled ${inserted} work items; work-items.json files kept as dual-write mirrors`);
  },
};
