require('../config/loadEnv')();
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const persistentStore = require('../services/persistentStore');
const service = require('../services/validatorTunnelTopologyService');
const { matchesValidatorTarget } = require('../services/validatorTargetBindingService');

const CLIENT_VERSIONS = new Set([
  '1.4.121-validator-direct-evidence-diagnostic-tunnel-fallback-locked',
  '1.4.122-validator-direct-offer-state-diagnostic-tunnel-fallback-locked',
  '1.4.123-validator-direct-control-heartbeat-diagnostic-tunnel-fallback-locked'
]);
const CONFIRMATION = 'ATTEST validator-1,validator-2,validator-3 EXISTING DIRECT LAN QUORUM';
const confirm = String(process.argv.find(value => value.startsWith('--confirm=')) || '').slice(10);
if (confirm !== CONFIRMATION) throw new Error('Exact direct LAN runtime attestation confirmation is required.');
const topology = JSON.parse(fs.readFileSync(service.paths.topologyPath, 'utf8'));
const direct = service.getDirectQuorum(topology);
if (!direct || direct.state !== 'STAGED') throw new Error('A staged direct LAN quorum is required.');
if (fs.existsSync(service.paths.approvalPath)) {
  const previous = JSON.parse(fs.readFileSync(service.paths.approvalPath, 'utf8'));
  const expiresAt = new Date(previous.expiresAt || 0).getTime();
  if (!['ACTIVATE_VALIDATOR_DIRECT_LAN_QUORUM', 'ATTEST_EXISTING_VALIDATOR_DIRECT_LAN_QUORUM'].includes(previous.action)
    || !Number.isFinite(expiresAt) || expiresAt > Date.now()) {
    throw new Error('A non-expired or unrelated validator approval is present.');
  }
  const historyRoot = path.join(path.dirname(service.paths.approvalPath), 'approval-history');
  fs.mkdirSync(historyRoot, { recursive: true });
  fs.renameSync(service.paths.approvalPath, path.join(historyRoot, `${previous.approvalId}-expired-status-incomplete.json`));
}
const nodes = persistentStore.readState().nodes || [];
for (const target of direct.targets) {
  const node = nodes.filter(row => matchesValidatorTarget(row, target))
    .sort((a, b) => new Date(b.lastHeartbeatAt || 0) - new Date(a.lastHeartbeatAt || 0))[0];
  const meta = node?.metadata || {};
  if (node?.status !== 'active' || Date.now() - new Date(node.lastHeartbeatAt || 0).getTime() > 3 * 60_000
    || !CLIENT_VERSIONS.has(node.clientVersion) || meta.validatorRuntimeState !== 'validator-active'
    || Number(meta.validatorRuntimeProcessPid || 0) <= 0 || Number(meta.validatorRuntimePeerCount || 0) < 2) {
    throw new Error(`Direct LAN runtime attestation readiness is incomplete: ${target.nodeName}.`);
  }
}
const approvedAt = new Date();
const approval = {
  schemaVersion: 'plais-validator-tunnel-migration-approval/v1',
  action: 'ATTEST_EXISTING_VALIDATOR_DIRECT_LAN_QUORUM',
  approvalId: `validator-direct-lan-attestation-${Date.now()}-${crypto.randomBytes(5).toString('hex')}`,
  targetNodeNames: direct.targetNodeNames,
  topologySha256: crypto.createHash('sha256').update(fs.readFileSync(service.paths.topologyPath)).digest('hex'),
  controls: { directLanQuorumAttestation: true, validatorProcessRestartAllowed: false,
    validatorKeyReadForIdentityCheckOnly: true, validatorKeyExportAllowed: false, publicRpcAllowed: false,
    externalTransactionAllowed: false, operatorSigningAllowed: false },
  approvedAt: approvedAt.toISOString(), expiresAt: new Date(approvedAt.getTime() + 10 * 60_000).toISOString()
};
const temporaryPath = `${service.paths.approvalPath}.${process.pid}.tmp`;
fs.writeFileSync(temporaryPath, `${JSON.stringify(approval, null, 2)}\n`, { encoding: 'utf8', flag: 'wx' });
fs.renameSync(temporaryPath, service.paths.approvalPath);
console.log(JSON.stringify({ ok: true, status: 'EXISTING_DIRECT_LAN_RUNTIME_ATTESTATION_APPROVED_NO_RESTART',
  approvalId: approval.approvalId, targetNodeNames: approval.targetNodeNames, expiresAt: approval.expiresAt,
  validatorProcessRestartAllowed: false }, null, 2));
