'use strict';

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

const services = [
  { id: 'aisfor', root: 'E:\\aisfor', entry: 'server.js', sockets: true, workerMarkers: ['passiveStandbyFence.workerExecutionAllowed', 'passiveStandbyFence.validatorRuntimeAllowed'] },
  { id: 'aistalk', root: 'F:\\aistalk', entry: 'server.js', sockets: true, workerMarkers: [] },
  { id: 'aisfor-group', root: 'E:\\aisfor-group', entry: 'app.js', sockets: false, workerMarkers: [] },
  { id: 'aismall', root: 'E:\\aismall', entry: 'app.js', sockets: true, workerMarkers: ['passiveStandbyFence.workerExecutionAllowed'] },
  { id: 'plai-sharing', root: 'F:\\plai-sharing', entry: 'server.js', socketEntry: 'services/liveSocketService.js', sockets: true, workerMarkers: ['passiveStandbyFence.workerExecutionAllowed'] }
];

function responseRecorder() {
  return {
    statusCode: 0,
    headers: {},
    body: '',
    setHeader(name, value) { this.headers[String(name).toLowerCase()] = String(value); },
    end(value = '') { this.body = String(value); }
  };
}

function invoke(fence, method, url) {
  const res = responseRecorder();
  let nextCalled = false;
  fence.middleware({ method, url }, res, () => { nextCalled = true; });
  return { res, nextCalled, body: res.body ? JSON.parse(res.body) : null };
}

const results = services.map(service => {
  const modulePath = path.join(service.root, 'services', 'passiveStandbyFence.js');
  const entryPath = path.join(service.root, service.entry);
  const { createPassiveStandbyFence } = require(modulePath);
  const primary = createPassiveStandbyFence({ serviceId: service.id, env: {} });
  const standby = createPassiveStandbyFence({ serviceId: service.id, env: { PLAI_SERVICE_MODE: 'PASSIVE_STANDBY' } });
  assert.strictEqual(primary.enabled, false);
  assert.strictEqual(primary.workerExecutionAllowed, true);
  assert.strictEqual(invoke(primary, 'POST', '/synthetic-write').nextCalled, true);
  assert.strictEqual(standby.enabled, true);
  assert.strictEqual(standby.workerExecutionAllowed, false);
  assert.strictEqual(standby.transactionSubmissionAllowed, false);
  assert.strictEqual(standby.validatorRuntimeAllowed, false);
  assert.strictEqual(invoke(standby, 'GET', '/__plai/standby-health').res.statusCode, 200);
  assert.strictEqual(invoke(standby, 'GET', '/public/recovery.css').nextCalled, true);
  assert.strictEqual(invoke(standby, 'GET', '/dynamic').body.code, 'PASSIVE_STANDBY_DYNAMIC_REQUEST_FENCED');
  assert.strictEqual(invoke(standby, 'POST', '/write').body.code, 'PASSIVE_STANDBY_WRITE_FENCED');
  assert.throws(() => createPassiveStandbyFence({
    serviceId: service.id,
    env: { PLAI_SERVICE_MODE: 'PASSIVE_STANDBY', PLAI_TRANSACTION_SUBMISSION_ENABLED: '1' }
  }), /PASSIVE_STANDBY_UNSAFE_FLAGS/);
  let socketFenced = !service.sockets;
  if (service.sockets) {
    let guard;
    standby.installSocketFence({ use(value) { guard = value; } });
    guard({}, error => { socketFenced = error?.message === 'PASSIVE_STANDBY_SOCKET_FENCED'; });
    assert.strictEqual(socketFenced, true);
  }
  const entrySource = fs.readFileSync(entryPath, 'utf8');
  assert.ok(entrySource.includes('passiveStandbyFence.middleware'));
  const socketSource = service.socketEntry
    ? fs.readFileSync(path.join(service.root, service.socketEntry), 'utf8') : entrySource;
  if (service.sockets) assert.ok(socketSource.includes('installSocketFence'));
  for (const marker of service.workerMarkers) assert.ok(entrySource.includes(marker));
  return {
    serviceId: service.id,
    primaryDefaultUnchanged: true,
    independentHealthReady: true,
    dynamicReadsFenced: true,
    writesFenced: true,
    socketsFenced: socketFenced,
    scheduledWorkersObserved: service.workerMarkers.length > 0,
    workersFenced: true,
    transactionSubmissionFenced: true,
    validatorRuntimeFenced: true
  };
});

process.stdout.write(`${JSON.stringify({
  ok: true,
  schemaVersion: 'plai-passive-service-fleet-fence-evidence/v1',
  serviceCount: results.length,
  services: results,
  activationDefault: 'PRIMARY_UNCHANGED',
  passiveActivationValue: 'PLAI_SERVICE_MODE=PASSIVE_STANDBY',
  productionProcessesRestarted: false,
  databaseChanged: false,
  dnsChanged: false,
  externalTransfersMade: false,
  validatorChanged: false,
  networkRequestsMade: false
}, null, 2)}\n`);
