/**
 * Vaultfire Protocol — Contract Registry
 *
 * Canonical entry point for all deployed Vaultfire Protocol contract addresses
 * and ABIs across Base and Avalanche mainnet.
 *
 * @package @vaultfire/contracts
 * @version 1.0.0
 */

import baseAddresses from "./addresses/base.json";
import avalancheAddresses from "./addresses/avalanche.json";

export { baseAddresses, avalancheAddresses };

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export type ChainName = "base" | "avalanche";

export type BaseContractName = keyof typeof baseAddresses.contracts;
export type AvalancheContractName = keyof typeof avalancheAddresses.contracts;

/** Union of all contract names across both chains. */
export type ContractName = BaseContractName | AvalancheContractName;

export interface ChainConfig {
  chainId: number;
  chainName: string;
  rpc: string;
  explorer: string;
  deployer: string;
  usdc: string;
  contracts: Record<string, string>;
}

// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------

const CHAIN_MAP: Record<ChainName, ChainConfig> = {
  base: baseAddresses as ChainConfig,
  avalanche: avalancheAddresses as ChainConfig,
};

// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------

/**
 * Returns the deployed address for a given contract on a given chain.
 *
 * @example
 * const addr = getAddress("base", "AIPartnershipBondsV2");
 * // "0xC574CF2a09B0B470933f0c6a3ef422e3fb25b4b4"
 *
 * @throws {Error} if the contract is not deployed on the specified chain.
 */
export function getAddress(chain: ChainName, contract: ContractName): string {
  const cfg = CHAIN_MAP[chain];
  const address = cfg.contracts[contract];
  if (!address) {
    throw new Error(
      `Contract "${contract}" is not deployed on chain "${chain}". ` +
        `Available contracts: ${Object.keys(cfg.contracts).join(", ")}`
    );
  }
  return address;
}

/**
 * Returns the block-explorer URL for a given address on a given chain.
 *
 * @example
 * const url = getExplorerUrl("base", "0x01C479F0c039fEC40c0Cf1c5C921bab457d57441");
 * // "https://basescan.org/address/0x01C479F0c039fEC40c0Cf1c5C921bab457d57441"
 */
export function getExplorerUrl(chain: ChainName, address: string): string {
  const { explorer } = CHAIN_MAP[chain];
  return `${explorer}/address/${address}`;
}

/**
 * Returns all contract name → address mappings for a given chain.
 *
 * @example
 * const contracts = getAllContracts("avalanche");
 * // { MissionEnforcement: "0xcf64...", ... }
 */
export function getAllContracts(chain: ChainName): Record<string, string> {
  return { ...CHAIN_MAP[chain].contracts };
}

/**
 * Returns the full chain configuration including RPC endpoint,
 * block explorer, deployer address, and USDC address.
 */
export function getChainConfig(chain: ChainName): ChainConfig {
  return CHAIN_MAP[chain];
}

/**
 * Returns the block-explorer URL for a given contract on a given chain.
 *
 * @example
 * const url = getContractExplorerUrl("base", "AIAccountabilityBondsV2");
 * // "https://basescan.org/address/0x6750D28865434344e04e1D0a6044394b726C3dfE"
 */
export function getContractExplorerUrl(
  chain: ChainName,
  contract: ContractName
): string {
  const address = getAddress(chain, contract);
  return getExplorerUrl(chain, address);
}

/**
 * Returns true if a contract is deployed on the specified chain.
 */
export function isDeployedOn(chain: ChainName, contract: string): boolean {
  return contract in CHAIN_MAP[chain].contracts;
}
