import { ethers } from 'ethers';
import { getChainConfig } from '../config/chains';
import type { OfficialProtocolContractRow } from './official-protocols-report';

export type ContractVerificationStatus = 'verified' | 'below_min' | 'no_code' | 'error';

export interface ContractVerificationRow {
  name: string;
  address: string;
  codeSize: number;
  minCodeSize?: number;
  status: ContractVerificationStatus;
}

export interface ProtocolVerificationReport {
  verifiedAt: string;
  chainId: number;
  rpcUsed: boolean;
  allVerified: boolean;
  contracts: ContractVerificationRow[];
}

export async function verifyProtocolContracts(
  chainId: number,
  contracts: OfficialProtocolContractRow[],
): Promise<ProtocolVerificationReport> {
  const chainConfig = getChainConfig(chainId);
  if (!chainConfig || contracts.length === 0) {
    return {
      verifiedAt: new Date().toISOString(),
      chainId,
      rpcUsed: false,
      allVerified: false,
      contracts: [],
    };
  }

  const provider = new ethers.JsonRpcProvider(chainConfig.rpcUrl);
  const rows: ContractVerificationRow[] = [];
  let allVerified = true;

  for (const contract of contracts) {
    if (!contract.address.startsWith('0x')) {
      rows.push({
        name: contract.name,
        address: contract.address,
        codeSize: 0,
        minCodeSize: contract.minCodeSize,
        status: 'no_code',
      });
      allVerified = false;
      continue;
    }

    try {
      const code = await provider.getCode(contract.address);
      const codeSize = Math.max(0, (code.length - 2) / 2);
      const minCodeSize = contract.minCodeSize ?? 1;
      let status: ContractVerificationStatus = 'verified';
      if (codeSize === 0) {
        status = 'no_code';
        allVerified = false;
      } else if (codeSize < minCodeSize) {
        status = 'below_min';
        allVerified = false;
      }
      rows.push({
        name: contract.name,
        address: contract.address,
        codeSize,
        minCodeSize: contract.minCodeSize,
        status,
      });
    } catch {
      rows.push({
        name: contract.name,
        address: contract.address,
        codeSize: 0,
        minCodeSize: contract.minCodeSize,
        status: 'error',
      });
      allVerified = false;
    }
  }

  return {
    verifiedAt: new Date().toISOString(),
    chainId,
    rpcUsed: true,
    allVerified,
    contracts: rows,
  };
}
