#!/usr/bin/env node
// ============================================================
// PedScribe maintenance CLI
// Usage:  node scripts/maintenance.js <command>
//
// Commands:
//   reindex        Rebuild all indexes + refresh collation version
//                  (run this after any Postgres image upgrade)
//   check          Report collation/index health, no writes
//   help           Show this message
// ============================================================

require('dotenv').config();
var { Pool } = require('pg');

var pool = new Pool({
  connectionString: process.env.DATABASE_URL
    || 'postgres://' + (process.env.DB_USER || 'pedscribe')
       + ':' + (process.env.DB_PASSWORD || process.env.POSTGRES_PASSWORD || '')
       + '@' + (process.env.DB_HOST || 'postgres')
       + ':' + (process.env.DB_PORT || 5432)
       + '/' + (process.env.DB_NAME || 'pedscribe')
});

function log(msg)   { process.stdout.write(msg + '\n'); }
function warn(msg)  { process.stderr.write('⚠️  ' + msg + '\n'); }
function ok(msg)    { process.stdout.write('✅ ' + msg + '\n'); }
function heading(m) { process.stdout.write('\n── ' + m + ' ──\n'); }

async function check() {
  var client = await pool.connect();
  try {
    heading('Postgres version');
    var v = await client.query('SELECT version()');
    log(v.rows[0].version);

    heading('Collation version');
    var d = await client.query(
      "SELECT datcollversion AS recorded, " +
      "pg_database_collation_actual_version(oid) AS actual " +
      "FROM pg_database WHERE datname = current_database()"
    );
    var row = d.rows[0] || {};
    log('Recorded:  ' + row.recorded);
    log('Library:   ' + row.actual);
    if (row.recorded && row.actual && row.recorded !== row.actual) {
      warn('Drift detected. Run `node scripts/maintenance.js reindex`');
    } else {
      ok('Aligned — no drift');
    }

    heading('Row counts');
    var tables = ['users', 'user_sessions', 'audit_log', 'saved_encounters', 'audio_backups'];
    for (var i = 0; i < tables.length; i++) {
      try {
        var c = await client.query('SELECT COUNT(*)::int AS n FROM ' + tables[i]);
        log(tables[i].padEnd(20) + c.rows[0].n);
      } catch (e) { log(tables[i].padEnd(20) + '(missing)'); }
    }

    heading('Text indexes');
    var idx = await client.query(
      "SELECT indexname, indexdef FROM pg_indexes " +
      "WHERE schemaname='public' AND (indexdef ILIKE '%email%' OR indexdef ILIKE '%token%' OR indexdef ILIKE '%slug%' OR indexdef ILIKE '%COLLATE%')"
    );
    idx.rows.forEach(function(r) {
      var hasC = /COLLATE "C"/.test(r.indexdef);
      log((hasC ? '[C] ' : '[  ] ') + r.indexname);
    });
  } finally { client.release(); }
}

async function reindex() {
  var client = await pool.connect();
  try {
    heading('REINDEX DATABASE');
    var start = Date.now();
    log('Running REINDEX DATABASE pedscribe (this can take a few seconds on small DBs, longer on large)...');
    await client.query('REINDEX DATABASE ' + (process.env.DB_NAME || 'pedscribe'));
    ok('REINDEX complete (' + ((Date.now() - start) / 1000).toFixed(1) + 's)');

    heading('REFRESH COLLATION VERSION');
    await client.query('ALTER DATABASE ' + (process.env.DB_NAME || 'pedscribe') + ' REFRESH COLLATION VERSION');
    ok('Collation version refreshed');

    heading('ANALYZE');
    await client.query('ANALYZE');
    ok('Statistics updated');

    log('\nAll done. You can now continue using the app normally.');
  } finally { client.release(); }
}

(async function main() {
  var cmd = process.argv[2] || 'help';
  try {
    if (cmd === 'reindex') await reindex();
    else if (cmd === 'check') await check();
    else {
      log('PedScribe maintenance CLI');
      log('');
      log('Commands:');
      log('  check      Report health (no writes)');
      log('  reindex    REINDEX + REFRESH COLLATION + ANALYZE');
      log('');
      log('Run inside the container:');
      log('  docker exec pediatric-ai-scribe node scripts/maintenance.js <cmd>');
      log('  docker exec pediatric-ai-scribe npm run maint:<cmd>');
    }
  } catch (e) {
    warn(e.message);
    process.exit(1);
  } finally {
    await pool.end();
  }
})();
