require('../config/loadEnv')();

const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const operatorCustodyService = require('../services/operatorCustodyService');

const projectRoot = path.join(__dirname, '..');
const migrationRoot = path.join(projectRoot, 'runtime', 'plais-qbft-canonical-migration');
const topologyPath = path.join(migrationRoot, 'topology.json');
const manifestPath = path.join(migrationRoot, 'encrypted-key-envelopes', 'manifest.json');
const attestationPath = path.join(projectRoot, 'runtime', 'mainnet-key-security-attestation.json');

function sha256File(filePath) {
  return crypto.createHash('sha256').update(fs.readFileSync(filePath)).digest('hex');
}

function parseJsonOutput(output) {
  const text = String(output || '').trim();
  const first = text.indexOf('{');
  const last = text.lastIndexOf('}');
  if (first < 0 || last < first) throw new Error('Audit did not return JSON.');
  return JSON.parse(text.slice(first, last + 1));
}

function runAudit(scriptName) {
  const result = spawnSync(process.execPath, [path.join(__dirname, scriptName)], {
    cwd: projectRoot,
    encoding: 'utf8',
    windowsHide: true,
    maxBuffer: 4 * 1024 * 1024
  });
  const data = parseJsonOutput(result.stdout || result.stderr);
  if (result.status !== 0 || data.ok !== true) {
    throw new Error(`${scriptName}: ${data.error || data.message || 'audit failed'}`);
  }
  return data;
}

function main() {
  const envelopes = runAudit('audit-encrypted-validator-key-envelopes.js');
  const deliveryLock = runAudit('validator-key-delivery-locked-self-test.js');
  const operatorCustody = runAudit('operator-key-custody-audit.js');
  const verifiedAt = new Date();
  const attestation = {
    schemaVersion: 'plais-mainnet-key-security-attestation/v1',
    verifiedAt: verifiedAt.toISOString(),
    expiresAt: new Date(verifiedAt.getTime() + 24 * 60 * 60 * 1000).toISOString(),
    bindings: {
      topologySha256: sha256File(topologyPath),
      envelopeManifestSha256: sha256File(manifestPath),
      operatorVaultSha256: sha256File(operatorCustodyService.resolveVaultPath())
    },
    checks: {
      encryptedValidatorEnvelopes: envelopes.state === 'ENCRYPTED_KEY_ENVELOPES_READY_NOT_DELIVERED'
        && Number(envelopes.validatorCount || 0) === 4,
      validatorKeyDeliveryLocked: deliveryLock.state === 'LOCKED_AWAITING_DELIVERY_APPROVAL'
        && Number(deliveryLock.validatorCount || 0) === 4,
      operatorCustody: operatorCustody.ok === true
    }
  };
  if (!Object.values(attestation.checks).every(Boolean)) {
    throw new Error('One or more privileged key security checks failed.');
  }
  const temporaryPath = `${attestationPath}.tmp`;
  fs.writeFileSync(temporaryPath, `${JSON.stringify(attestation, null, 2)}\n`, { flag: 'wx' });
  fs.renameSync(temporaryPath, attestationPath);
  console.log(JSON.stringify({
    ok: true,
    state: 'KEY_SECURITY_ATTESTED',
    attestationPath,
    verifiedAt: attestation.verifiedAt,
    expiresAt: attestation.expiresAt,
    checks: attestation.checks
  }, null, 2));
}

try {
  main();
} catch (error) {
  console.error(JSON.stringify({
    ok: false,
    state: 'KEY_SECURITY_ATTESTATION_FAILED',
    error: error.code || 'KEY_SECURITY_ATTESTATION_FAILED',
    message: error.message
  }, null, 2));
  process.exit(1);
}
