import { CHAIN_CONFIG, getChainConfig, getSupportedChains, VaultfireChain } from '../src/chains';

describe('Chain Configuration', () => {
  test('all 4 chains are configured', () => {
    const chains = getSupportedChains();
    expect(chains).toHaveLength(4);
    expect(chains).toContain('base');
    expect(chains).toContain('avalanche');
    expect(chains).toContain('arbitrum');
    expect(chains).toContain('polygon');
  });

  test('each chain has correct chain IDs', () => {
    expect(CHAIN_CONFIG.base.chainId).toBe(8453);
    expect(CHAIN_CONFIG.avalanche.chainId).toBe(43114);
    expect(CHAIN_CONFIG.arbitrum.chainId).toBe(42161);
    expect(CHAIN_CONFIG.polygon.chainId).toBe(137);
  });

  test('each chain has all required contracts', () => {
    for (const chain of getSupportedChains()) {
      const c = CHAIN_CONFIG[chain].contracts;
      expect(c.identity).toMatch(/^0x[0-9a-fA-F]{40}$/);
      expect(c.partnership).toMatch(/^0x[0-9a-fA-F]{40}$/);
      expect(c.accountability).toMatch(/^0x[0-9a-fA-F]{40}$/);
      expect(c.reputation).toMatch(/^0x[0-9a-fA-F]{40}$/);
      expect(c.bridge).toMatch(/^0x[0-9a-fA-F]{40}$/);
    }
  });

  test('All 4 chains have distinct identity registry addresses', () => {
    const ids = (['base', 'avalanche', 'arbitrum', 'polygon'] as const).map(
      (c) => CHAIN_CONFIG[c].contracts.identity
    );
    expect(new Set(ids).size).toBe(4);
  });

  test('Base and Avalanche have different addresses', () => {
    expect(CHAIN_CONFIG.base.contracts.identity).not.toBe(CHAIN_CONFIG.avalanche.contracts.identity);
  });

  test('Base and Arbitrum have different addresses', () => {
    expect(CHAIN_CONFIG.base.contracts.identity).not.toBe(CHAIN_CONFIG.arbitrum.contracts.identity);
  });

  test('getChainConfig by name', () => {
    const config = getChainConfig('base');
    expect(config.name).toBe('Base');
    expect(config.chainId).toBe(8453);
  });

  test('getChainConfig by chain ID', () => {
    const config = getChainConfig(42161);
    expect(config.name).toBe('Arbitrum');
  });

  test('getChainConfig throws for invalid chain', () => {
    expect(() => getChainConfig('solana' as VaultfireChain)).toThrow('Unsupported chain');
    expect(() => getChainConfig(999)).toThrow('Unsupported chain');
  });

  test('each chain has valid RPC URL', () => {
    for (const chain of getSupportedChains()) {
      expect(CHAIN_CONFIG[chain].rpcUrl).toMatch(/^https:\/\//);
    }
  });

  test('each chain has valid explorer URL', () => {
    for (const chain of getSupportedChains()) {
      expect(CHAIN_CONFIG[chain].explorer).toMatch(/^https:\/\//);
    }
  });

  test('contract addresses are checksummed or valid hex', () => {
    for (const chain of getSupportedChains()) {
      const contracts = CHAIN_CONFIG[chain].contracts;
      for (const [name, addr] of Object.entries(contracts)) {
        if (addr) {
          expect(addr).toMatch(/^0x[0-9a-fA-F]{40}$/);
        }
      }
    }
  });

  test('VNS contracts exist on Base, Arbitrum, and Polygon', () => {
    expect(CHAIN_CONFIG.base.contracts.vns).toBeDefined();
    expect(CHAIN_CONFIG.arbitrum.contracts.vns).toBeDefined();
    expect(CHAIN_CONFIG.polygon.contracts.vns).toBeDefined();
  });
});
