const fs = require('fs');
const path = require('path');
const persistentStore = require('./persistentStore');
const readMonitorService = require('./ledgerMongoReadMonitorService');
const mongoReadAdapter = require('./mongoLedgerReadAdapter');
const readBackendSwitchService = require('./ledgerReadBackendSwitchService');
const readSwitchApprovalService = require('./ledgerReadSwitchApprovalService');

function getDataDir() {
  const info = persistentStore.getStorageInfo ? persistentStore.getStorageInfo() : {};
  return info.dataDir || path.dirname(info.ledgerPath || persistentStore.getLedgerPath());
}

function guardPath() {
  return path.join(getDataDir(), 'mongo-post-switch-guard.json');
}

function readJson(filePath, fallback) {
  try {
    const stat = fs.statSync(filePath);
    return { ...JSON.parse(fs.readFileSync(filePath, 'utf8')), exists: true, fileUpdatedAt: stat.mtime.toISOString() };
  } catch (err) {
    return { ...fallback, exists: false, fileUpdatedAt: null, path: filePath };
  }
}

function writeJson(filePath, body) {
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
  fs.writeFileSync(filePath, `${JSON.stringify(body, null, 2)}\n`);
}

async function checkEndpoint(url) {
  const startedAt = Date.now();
  try {
    const response = await fetch(url, { signal: AbortSignal.timeout(5000) });
    return {
      url,
      ok: response.status >= 200 && response.status < 400,
      statusCode: response.status,
      durationMs: Date.now() - startedAt
    };
  } catch (err) {
    return {
      url,
      ok: false,
      statusCode: 0,
      durationMs: Date.now() - startedAt,
      error: err.message
    };
  }
}

async function runGuard(options = {}) {
  const port = process.env.PORT || 4317;
  const baseUrl = options.baseUrl || `http://127.0.0.1:${port}`;
  const monitor = await readMonitorService.runSample({ reason: options.reason || 'post-switch-guard' });
  const endpoints = await Promise.all([
    checkEndpoint(`${baseUrl}/admin`),
    checkEndpoint(`${baseUrl}/explorer`),
    checkEndpoint(`${baseUrl}/admin/ledger-migration`)
  ]);
  const readGate = mongoReadAdapter.getStatus();
  const switchStatus = readBackendSwitchService.getStatus();
  const endpointOk = endpoints.every((row) => row.ok);
  const healthy = Boolean(monitor.monitor.latestSample && monitor.monitor.latestSample.ok && endpointOk);
  let rollbackPrepared = false;
  let rollbackReason = '';

  if (!healthy && options.rollbackOnFailure && options.confirmRollback && switchStatus.readBackend === 'mongodb') {
    rollbackReason = 'post-switch guard detected unhealthy Mongo read promotion';
    readBackendSwitchService.setReadBackend('json-file', {
      actor: options.actor || 'post-switch-guard',
      reason: rollbackReason
    });
    readSwitchApprovalService.revoke({
      revokedBy: options.actor || 'post-switch-guard',
      reason: rollbackReason
    });
    rollbackPrepared = true;
  }

  const output = {
    ok: healthy,
    mode: 'mongo-post-switch-guard',
    readGate,
    requestedBackend: switchStatus.readBackend,
    monitor: monitor.monitor,
    endpoints,
    endpointOk,
    rollbackPrepared,
    rollbackReason,
    checkedAt: new Date().toISOString(),
    path: guardPath()
  };
  writeJson(output.path, output);
  return output;
}

function getStatus() {
  return readJson(guardPath(), {
    ok: false,
    mode: 'not-run',
    readGate: mongoReadAdapter.getStatus(),
    requestedBackend: readBackendSwitchService.getReadBackend(),
    monitor: readMonitorService.getStatus(),
    endpoints: [],
    endpointOk: false,
    rollbackPrepared: false,
    rollbackReason: '',
    path: guardPath()
  });
}

module.exports = {
  runGuard,
  getStatus,
  guardPath
};
