#!/usr/bin/env node
// Verify ALL 12 unverified Vaultfire contracts on Base mainnet via
// BaseScan v2 API. Constructor args derived from on-chain reads.
// Submits all in parallel, then polls patiently (up to ~5 min per).

import fs from 'fs';
import { AbiCoder } from 'ethers';

const API_KEY = process.env.ETHERSCAN_API_KEY || process.env.BASESCAN_API_KEY;
if (!API_KEY) { console.error('Set ETHERSCAN_API_KEY'); process.exit(1); }

const BUILD = JSON.parse(fs.readFileSync('artifacts/build-info/8720fddb37e8ae8728f250c45f08338d.json','utf8'));
const STD = {
  language: 'Solidity',
  sources: BUILD.input.sources,
  settings: {
    optimizer: BUILD.input.settings.optimizer,
    evmVersion: BUILD.input.settings.evmVersion,
    viaIR: BUILD.input.settings.viaIR,
    outputSelection: { '*': { '*': ['evm.bytecode','evm.deployedBytecode','abi'] } },
  }
};
const coder = AbiCoder.defaultAbiCoder();

// All 12 unverified contracts
const TARGETS = [
  // [address, contracts/Path.sol:Name, ctorTypes, ctorValues]
  ['0xa7BD20bf5De63df949cA5Be2F20835978eCba81A', 'contracts/ERC8004IdentityRegistry.sol:ERC8004IdentityRegistry', [], []],
  ['0x01C479F0c039fEC40c0Cf1c5C921bab457d57441', 'contracts/AIPartnershipBondsV2.sol:AIPartnershipBondsV2', [], []],
  ['0xf7B2dC73Ec69528F171F4a0ded62da557866BaA5', 'contracts/FlourishingMetricsOracle.sol:FlourishingMetricsOracle', [], []],
  ['0x32211773C8266774A704aeD471f8eF073f34bA79', 'contracts/BeliefAttestationVerifier.sol:BeliefAttestationVerifier', [], []],
  ['0x6750D28865434344e04e1D0a6044394b726C3dfE', 'contracts/AIAccountabilityBondsV2.sol:AIAccountabilityBondsV2',
    ['address'], ['0xA054f831B562e729F8D268291EBde1B2EDcFb84F']],
  ['0x98afd1440B2238D73c1394720277a6d031fCbbD0', 'contracts/ERC8004ReputationRegistry.sol:ERC8004ReputationRegistry',
    ['address'], ['0xa7BD20bf5De63df949cA5Be2F20835978eCba81A']],
  ['0x8D3495772EAcAdB7dC09F1784eF06F2D109fb8a5', 'contracts/ERC8004ValidationRegistry.sol:ERC8004ValidationRegistry',
    ['address','address'], ['0xa7BD20bf5De63df949cA5Be2F20835978eCba81A','0x32211773C8266774A704aeD471f8eF073f34bA79']],
  ['0x8bEFe7411AecddA6E1Aea8F031fedD293Ca7372E', 'contracts/VaultfireERC8004Adapter.sol:VaultfireERC8004Adapter',
    ['address','address','address','address'],
    ['0x01C479F0c039fEC40c0Cf1c5C921bab457d57441','0xa7BD20bf5De63df949cA5Be2F20835978eCba81A',
     '0x98afd1440B2238D73c1394720277a6d031fCbbD0','0x8D3495772EAcAdB7dC09F1784eF06F2D109fb8a5']],
  ['0x2a46B5932e9559176241056A04a608B8fEbCc5A7', 'contracts/ProductionBeliefAttestationVerifier.sol:ProductionBeliefAttestationVerifier',
    ['address','bytes32'],
    ['0xA054f831B562e729F8D268291EBde1B2EDcFb84F',
     '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff']],
  ['0x34a19C7298aCA59e185F1ecfB352AC566bB4B4A9', 'contracts/MultisigGovernance.sol:MultisigGovernance',
    ['address[]','uint256'],
    [['0xA054f831B562e729F8D268291EBde1B2EDcFb84F','0x909f0197F0c28BD4fF72A261Eb7f9cadf88eD3c8'], 2n]],
  ['0xef703bBe9b21960ede3e96abBB0Bbd0c525Fe050', 'contracts/DilithiumAttestor.sol:DilithiumAttestor',
    ['address','bool','address'],
    ['0xA054f831B562e729F8D268291EBde1B2EDcFb84F', false, '0x0000000000000000000000000000000000000000']],
  ['0x62edf0cBc8Fa3d98B6A07197DFE9cb1c128a7eC7', 'contracts/teleporter/VaultfireTeleporterBridge.sol:VaultfireTeleporterBridge',
    ['address','uint256'],
    ['0x0000000000000000000000000000000000000000', 500000n]],
];

const sleep = ms => new Promise(r => setTimeout(r, ms));

async function submit(t) {
  const [addr, key, types, values] = t;
  const ctor = types.length === 0 ? '' : coder.encode(types, values).slice(2);
  const body = new URLSearchParams({
    module: 'contract', action: 'verifysourcecode',
    contractaddress: addr,
    codeformat: 'solidity-standard-json-input',
    sourceCode: JSON.stringify(STD),
    contractname: key,
    compilerversion: 'v0.8.25+commit.b61c2a91',
    constructorArguements: ctor,
  });
  const r = await fetch(`https://api.etherscan.io/v2/api?chainid=8453&apikey=${API_KEY}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: body.toString(),
  });
  return await r.json();
}

async function checkStatus(guid) {
  const u = `https://api.etherscan.io/v2/api?chainid=8453&module=contract&action=checkverifystatus&apikey=${API_KEY}&guid=${guid}`;
  const r = await fetch(u);
  return await r.json();
}

async function checkVerified(addr) {
  const u = `https://api.etherscan.io/v2/api?chainid=8453&module=contract&action=getsourcecode&address=${addr}&apikey=${API_KEY}`;
  const r = await fetch(u);
  const j = await r.json();
  return Boolean(j.result?.[0]?.ContractName);
}

const log = (...a) => console.log(new Date().toISOString().slice(11,19), ...a);

// 1) Submit all
log(`Submitting ${TARGETS.length} verification jobs...`);
const submissions = [];
for (const t of TARGETS) {
  const [addr, key] = t;
  const j = await submit(t);
  const ok = j.status === '1';
  log(`  ${ok ? '→' : '✗'} ${key.split(':')[1].padEnd(40)} ${ok ? 'guid=' + j.result : 'err=' + j.result}`);
  submissions.push({ addr, contract: key.split(':')[1], guid: ok ? j.result : null, error: ok ? null : j.result });
  await sleep(800);
}

// 2) Poll patiently — up to 5 min total
log('\nPolling status (up to 5 min per contract)...');
const startTime = Date.now();
const maxMs = 5 * 60 * 1000;

while (Date.now() - startTime < maxMs) {
  const stillPending = submissions.filter(s => s.guid && !s.finalStatus);
  if (stillPending.length === 0) break;

  for (const s of stillPending) {
    try {
      // Prefer source-code check (definitive)
      const verified = await checkVerified(s.addr);
      if (verified) { s.finalStatus = '✅'; s.finalMsg = 'verified'; continue; }

      const c = await checkStatus(s.guid);
      const r = String(c.result || '');
      if (c.status === '1' && r.toLowerCase().includes('verified')) {
        s.finalStatus = '✅'; s.finalMsg = r;
      } else if (r && !r.toLowerCase().includes('pending')) {
        s.finalStatus = '❌'; s.finalMsg = r;
      }
    } catch (e) {}
    await sleep(500);
  }

  const done = submissions.filter(s => s.finalStatus).length;
  const elapsed = Math.floor((Date.now() - startTime) / 1000);
  log(`  ${done}/${submissions.length} done after ${elapsed}s`);
  await sleep(20000); // poll every 20s
}

// 3) Final check via source-code endpoint
log('\nFinal status (via getsourcecode):');
for (const s of submissions) {
  const verified = await checkVerified(s.addr);
  s.finalStatus = verified ? '✅' : (s.finalStatus || '❌');
  log(`  ${s.finalStatus} ${s.contract.padEnd(40)} ${s.addr}  ${verified ? 'VERIFIED' : (s.finalMsg || s.error || 'unknown')}`);
  await sleep(250);
}

const verifiedCount = submissions.filter(s => s.finalStatus === '✅').length;
console.log(`\n${verifiedCount}/${submissions.length} verified`);

// Persist results
fs.writeFileSync('verify-results.json', JSON.stringify(submissions, null, 2));
log('Results saved to verify-results.json');
