import { runMigrations } from '../../engines/schema/migrate.js';
export const ARCHITECTS_SCHEMA = `
CREATE TABLE IF NOT EXISTS architects_blueprints (
  id             TEXT PRIMARY KEY,
  strike_team_id TEXT,
  title          TEXT NOT NULL,
  workflow_id    TEXT,
  status         TEXT NOT NULL DEFAULT 'active'
    CHECK(status IN ('draft','active','converging','done','archived')),
  variables      TEXT NOT NULL DEFAULT '{}',
  worklist_id    TEXT,
  created_at     TEXT NOT NULL DEFAULT (datetime('now'))
);

CREATE TABLE IF NOT EXISTS architects_worklists (
  id           TEXT PRIMARY KEY,
  blueprint_id TEXT NOT NULL,
  title        TEXT NOT NULL,
  created_at   TEXT NOT NULL DEFAULT (datetime('now'))
);

CREATE TABLE IF NOT EXISTS architects_work_items (
  id                    TEXT PRIMARY KEY,
  worklist_id           TEXT NOT NULL,
  title                 TEXT NOT NULL,
  parent_work_item_id   TEXT,
  correlation_id        TEXT,
  ancestry_path         TEXT NOT NULL DEFAULT '[]',
  status                TEXT NOT NULL DEFAULT 'todo'
    CHECK(status IN ('todo','claimed','in_progress','done','failed','blocked','cancelled')),
  depends_on            TEXT NOT NULL DEFAULT '[]',
  assigned_operative_id TEXT,
  construction_lock_id  TEXT,
  branch                TEXT,
  merged_at             TEXT,
  created_at            TEXT NOT NULL DEFAULT (datetime('now'))
);

CREATE TABLE IF NOT EXISTS architects_construction_locks (
  id            TEXT PRIMARY KEY,
  work_item_id  TEXT NOT NULL,
  operative_id  TEXT NOT NULL,
  acquired_at   TEXT NOT NULL DEFAULT (datetime('now')),
  released_at   TEXT,
  lease_duration_ms INTEGER NOT NULL DEFAULT 300000,
  lease_renewed_at  INTEGER,
  lease_expires_at  INTEGER NOT NULL DEFAULT 0,
  hook_ref      TEXT
);

CREATE TABLE IF NOT EXISTS architects_relay_messages (
  id                TEXT PRIMARY KEY,
  from_operative_id TEXT NOT NULL,
  to_operative_id   TEXT,
  strike_team_id    TEXT,
  subject           TEXT NOT NULL,
  body              TEXT NOT NULL,
  sent_at           TEXT NOT NULL DEFAULT (datetime('now')),
  read_at           TEXT,
  priority          TEXT NOT NULL DEFAULT 'normal'
    CHECK(priority IN ('normal','urgent'))
);

CREATE TABLE IF NOT EXISTS architects_convergence_runs (
  id             TEXT PRIMARY KEY,
  worklist_id    TEXT NOT NULL,
  strategy       TEXT NOT NULL DEFAULT 'bisecting'
    CHECK(strategy IN ('sequential','bisecting')),
  work_item_ids  TEXT NOT NULL DEFAULT '[]',
  status         TEXT NOT NULL DEFAULT 'running'
    CHECK(status IN ('running','merged','failed','bisecting','deferred')),
  failed_item_id TEXT,
  started_at     TEXT NOT NULL DEFAULT (datetime('now')),
  completed_at   TEXT
);

CREATE TABLE IF NOT EXISTS architects_dispatch_queue (
  id             TEXT PRIMARY KEY,
  operative_id   TEXT NOT NULL,
  work_item_id   TEXT NOT NULL,
  scheduled_at   TEXT NOT NULL DEFAULT (datetime('now')),
  dispatched_at  TEXT,
  status         TEXT NOT NULL DEFAULT 'queued'
    CHECK(status IN ('queued','dispatched','failed'))
);

CREATE INDEX IF NOT EXISTS idx_arch_items_worklist   ON architects_work_items(worklist_id, status);
CREATE INDEX IF NOT EXISTS idx_arch_items_operative  ON architects_work_items(assigned_operative_id);
CREATE INDEX IF NOT EXISTS idx_arch_locks_item       ON architects_construction_locks(work_item_id, released_at);
CREATE INDEX IF NOT EXISTS idx_arch_blueprints_team   ON architects_blueprints(strike_team_id, worklist_id);
CREATE INDEX IF NOT EXISTS idx_arch_relay_to_op      ON architects_relay_messages(to_operative_id, read_at);
CREATE INDEX IF NOT EXISTS idx_arch_relay_to_team    ON architects_relay_messages(strike_team_id, read_at);
`;
function hasColumn(db, table, column) {
    const rows = db.prepare(`PRAGMA table_info(${table})`).all();
    return rows.some((row) => row.name === column);
}
function addColumnIfMissing(db, table, column, ddl) {
    if (hasColumn(db, table, column))
        return;
    db.prepare(ddl).run();
}
/**
 * Migrate architects_work_items to allow 'cancelled' status.
 *
 * SQLite cannot ALTER a CHECK constraint, so we recreate the table when the
 * existing CHECK does not include 'cancelled'. Safe to call on new databases
 * (the table won't exist yet — `CREATE TABLE IF NOT EXISTS` in ARCHITECTS_SCHEMA
 * already includes 'cancelled', so nothing needs doing).
 */
function migrateWorkItemCancelledStatus(db) {
    const existing = db.prepare(`SELECT sql FROM sqlite_master WHERE type='table' AND name='architects_work_items'`).get();
    if (!existing?.sql)
        return; // new DB — schema string already has 'cancelled'
    if (existing.sql.includes("'cancelled'"))
        return; // already migrated
    db.exec(`
    CREATE TABLE IF NOT EXISTS architects_work_items_v2 (
      id                    TEXT PRIMARY KEY,
      worklist_id           TEXT NOT NULL,
      title                 TEXT NOT NULL,
      parent_work_item_id   TEXT,
      correlation_id        TEXT,
      ancestry_path         TEXT NOT NULL DEFAULT '[]',
      status                TEXT NOT NULL DEFAULT 'todo'
        CHECK(status IN ('todo','claimed','in_progress','done','failed','blocked','cancelled')),
      depends_on            TEXT NOT NULL DEFAULT '[]',
      assigned_operative_id TEXT,
      construction_lock_id  TEXT,
      branch                TEXT,
      merged_at             TEXT,
      created_at            TEXT NOT NULL DEFAULT (datetime('now'))
    );
    INSERT OR IGNORE INTO architects_work_items_v2 SELECT * FROM architects_work_items;
    DROP TABLE architects_work_items;
    ALTER TABLE architects_work_items_v2 RENAME TO architects_work_items;
    CREATE INDEX IF NOT EXISTS idx_arch_items_worklist  ON architects_work_items(worklist_id, status);
    CREATE INDEX IF NOT EXISTS idx_arch_items_operative ON architects_work_items(assigned_operative_id);
  `);
}
export function initArchitectsSchema(db) {
    // File-based forward-only migrations (PRAGMA user_version scheme).
    runMigrations(db, 'architects');
    db.exec(ARCHITECTS_SCHEMA);
    migrateWorkItemCancelledStatus(db);
    addColumnIfMissing(db, 'architects_work_items', 'parent_work_item_id', 'ALTER TABLE architects_work_items ADD COLUMN parent_work_item_id TEXT');
    addColumnIfMissing(db, 'architects_work_items', 'correlation_id', 'ALTER TABLE architects_work_items ADD COLUMN correlation_id TEXT');
    addColumnIfMissing(db, 'architects_work_items', 'ancestry_path', "ALTER TABLE architects_work_items ADD COLUMN ancestry_path TEXT NOT NULL DEFAULT '[]'");
    addColumnIfMissing(db, 'architects_construction_locks', 'lease_duration_ms', 'ALTER TABLE architects_construction_locks ADD COLUMN lease_duration_ms INTEGER NOT NULL DEFAULT 300000');
    addColumnIfMissing(db, 'architects_construction_locks', 'lease_renewed_at', 'ALTER TABLE architects_construction_locks ADD COLUMN lease_renewed_at INTEGER');
    addColumnIfMissing(db, 'architects_construction_locks', 'lease_expires_at', 'ALTER TABLE architects_construction_locks ADD COLUMN lease_expires_at INTEGER NOT NULL DEFAULT 0');
    db.exec('CREATE INDEX IF NOT EXISTS idx_arch_locks_expiry ON architects_construction_locks(work_item_id, lease_expires_at, released_at)');
    db.prepare(`
    UPDATE architects_construction_locks
    SET lease_expires_at = CASE
      WHEN lease_expires_at IS NULL OR lease_expires_at = 0 THEN CAST(strftime('%s', acquired_at) AS INTEGER) * 1000 + lease_duration_ms
      ELSE lease_expires_at
    END
  `).run();
}
