#!/usr/bin/env node
// Direct BaseScan API verification using standard JSON input.
// More reliable than `npx hardhat verify` because we skip the local
// bytecode-match check (which fails when source has been edited
// post-deploy even if functionally equivalent) and let BaseScan
// match against deployed bytecode directly.
//
// Usage: ETHERSCAN_API_KEY=... node scripts/verify-via-api.mjs

import fs from 'fs';
import path from 'path';

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

const BUILD_INFO = JSON.parse(
  fs.readFileSync('artifacts/build-info/8720fddb37e8ae8728f250c45f08338d.json', 'utf8')
);

const STANDARD_INPUT = {
  language: 'Solidity',
  sources: BUILD_INFO.input.sources,
  settings: {
    optimizer: BUILD_INFO.input.settings.optimizer,
    evmVersion: BUILD_INFO.input.settings.evmVersion,
    viaIR: BUILD_INFO.input.settings.viaIR,
    outputSelection: {
      '*': { '*': ['evm.bytecode', 'evm.deployedBytecode', 'abi'] }
    }
  }
};

// AbiCoder for constructor arg encoding
import { AbiCoder } from 'ethers';
const coder = AbiCoder.defaultAbiCoder();

// Each entry: [address, contractFile:ContractName, ctorArgTypes, ctorArgValues]
const TARGETS = [
  ['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'],
    ['0xfA15Ee28939B222B0448261A22156070f0A7813C',
     '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff']],
];

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

async function submitVerification(target) {
  const [addr, contractKey, types, values] = target;

  const ctorArgs = types.length === 0
    ? ''
    : coder.encode(types, values).slice(2); // strip 0x

  const body = new URLSearchParams({
    module: 'contract',
    action: 'verifysourcecode',
    contractaddress: addr,
    codeformat: 'solidity-standard-json-input',
    sourceCode: JSON.stringify(STANDARD_INPUT),
    contractname: contractKey,
    compilerversion: 'v0.8.25+commit.b61c2a91',
    constructorArguements: ctorArgs,
  });

  // v2 API requires chainid + apikey as query params
  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(),
  });
  const j = await r.json();
  return j;
}

async function checkStatus(guid) {
  const params = new URLSearchParams({
    chainid: '8453',
    module: 'contract',
    action: 'checkverifystatus',
    apikey: API_KEY,
    guid,
  });
  const r = await fetch('https://api.etherscan.io/v2/api?' + params.toString());
  return await r.json();
}

const results = [];

for (const target of TARGETS) {
  const [addr, key] = target;
  console.log(`\n▶ ${key.split(':')[1]} @ ${addr}`);
  const sub = await submitVerification(target);
  console.log(`  submit: status=${sub.status} message=${sub.message} result=${(sub.result||'').slice(0,80)}`);

  if (sub.status !== '1') {
    results.push({ addr, contract: key, ok: false, reason: sub.result || sub.message });
    await sleep(800);
    continue;
  }

  const guid = sub.result;
  // Poll up to 30s
  let final = null;
  for (let i = 0; i < 15; i++) {
    await sleep(2000);
    const c = await checkStatus(guid);
    if (c.status === '1') { final = { ok: true, msg: c.result }; break; }
    if (c.result && !c.result.toLowerCase().includes('pending')) {
      final = { ok: false, msg: c.result };
      break;
    }
  }
  if (!final) final = { ok: false, msg: 'timed out polling' };
  console.log(`  result: ${final.ok ? '✅' : '❌'} ${final.msg}`);
  results.push({ addr, contract: key, ok: final.ok, reason: final.msg });
  await sleep(1000);
}

console.log('\n================ SUMMARY ================');
for (const r of results) {
  const c = r.contract.split(':')[1];
  console.log(`${r.ok ? '✅' : '❌'} ${c.padEnd(40)} ${r.addr}  ${r.ok ? '' : '— ' + r.reason.slice(0,80)}`);
}
const okCount = results.filter(r=>r.ok).length;
console.log(`\n${okCount}/${results.length} verified`);
