import { describe, expect, it } from 'vitest'
import { buildMeshCounterpartRows, inferMeshSeed } from './meshCounterparts'

const wrappedRows = [
  {
    chainId: 1,
    chainName: 'Ethereum Mainnet',
    symbol: 'cWUSDC',
    address: '0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a',
  },
  {
    chainId: 56,
    chainName: 'BNB Chain',
    symbol: 'cWUSDC',
    address: '0x5355148C4740fcc3D7a96F05EdD89AB14851206b',
  },
  {
    chainId: 138,
    chainName: 'Chain 138',
    symbol: 'cUSDC',
    address: '0xf22258f57794CC8E06237084b353Ab30fFfa640b',
  },
]

const curated = [
  {
    chainId: 138,
    symbol: 'cUSDC',
    address: '0xf22258f57794CC8E06237084b353Ab30fFfa640b',
  },
]

describe('inferMeshSeed', () => {
  it('detects hub symbol from curated tokens', () => {
    expect(inferMeshSeed('cUSDC', curated, wrappedRows)).toMatchObject({
      hubSymbol: 'cUSDC',
      wrappedSymbol: 'cWUSDC',
      hubAddress: '0xf22258f57794CC8E06237084b353Ab30fFfa640b',
      needsHubResolve: false,
      matchReason: 'hub symbol',
    })
  })

  it('detects wrapped symbol and resolves hub from registry', () => {
    expect(inferMeshSeed('cWUSDC', curated, wrappedRows)).toMatchObject({
      hubSymbol: 'cUSDC',
      wrappedSymbol: 'cWUSDC',
      hubAddress: '0xf22258f57794CC8E06237084b353Ab30fFfa640b',
      matchReason: 'wrapped symbol',
    })
  })

  it('detects off-home wrapped address and flags hub resolve when hub unknown', () => {
    const seed = inferMeshSeed('0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a', [], wrappedRows)
    expect(seed).toMatchObject({
      hubSymbol: 'cUSDC',
      sourceChainId: 1,
      sourceAddress: '0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a',
      needsHubResolve: false,
      hubAddress: '0xf22258f57794CC8E06237084b353Ab30fFfa640b',
    })
  })

  it('returns null for unrelated queries', () => {
    expect(inferMeshSeed('random', curated, wrappedRows)).toBeNull()
  })
})

describe('buildMeshCounterpartRows', () => {
  it('merges token-mapping resolves with registry rows', () => {
    const seed = inferMeshSeed('cUSDC', curated, wrappedRows)!
    const resolved = new Map<number, string>([
      [138, seed.hubAddress!],
      [1, '0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a'],
    ])
    const chainNames = new Map<number, string>([
      [138, 'Chain 138'],
      [1, 'Ethereum Mainnet'],
      [56, 'BNB Chain'],
    ])
    const rows = buildMeshCounterpartRows(seed, resolved, wrappedRows, chainNames)
    expect(rows.map((row) => row.chainId)).toEqual([138, 1, 56])
    expect(rows[0].role).toBe('hub')
    expect(rows.filter((row) => row.chainId === 56)).toHaveLength(1)
  })
})
