import type { TokenListToken } from './config'
import { fetchPublicJson } from '@/utils/publicExplorer'

export type TokenListSurface = 'wallet' | 'catalog' | 'extended'

export const TOKEN_LIST_SURFACE_LABELS: Record<TokenListSurface, string> = {
  wallet: 'Canonical Chain 138 report list (wallet and MetaMask)',
  catalog: 'Canonical Chain 138 trading set',
  extended: 'Extended Metamask dual-chain catalog',
}

const REPORT_TOKEN_LIST_PATH = '/api/v1/report/token-list?chainId=138'
const CONFIG_TOKEN_LIST_PATH = '/api/config/token-list'

export function filterChain138Tokens(tokens: TokenListToken[], chainId = 138): TokenListToken[] {
  return tokens
    .filter((token) => token.chainId === chainId && typeof token.address === 'string' && token.address.trim().length > 0)
    .sort((left, right) => (left.symbol || left.name || '').localeCompare(right.symbol || right.name || ''))
}

export function mergeTokenListLookups(
  primary: TokenListToken[],
  secondary: TokenListToken[],
): Map<string, TokenListToken> {
  const lookup = new Map<string, TokenListToken>()
  for (const token of secondary) {
    if (token.address) {
      lookup.set(token.address.toLowerCase(), token)
    }
  }
  for (const token of primary) {
    if (token.address) {
      lookup.set(token.address.toLowerCase(), token)
    }
  }
  return lookup
}

export async function fetchTokenListForSurface(
  surface: TokenListSurface,
  chainId = 138,
): Promise<{ tokens: TokenListToken[]; source: 'report' | 'config' }> {
  if (surface === 'extended') {
    const configResult = await fetchPublicJson<{ tokens?: TokenListToken[] }>(CONFIG_TOKEN_LIST_PATH).catch(() => null)
    return {
      tokens: filterChain138Tokens(Array.isArray(configResult?.tokens) ? configResult.tokens : [], chainId),
      source: 'config',
    }
  }

  const reportResult = await fetchPublicJson<{ tokens?: TokenListToken[] }>(REPORT_TOKEN_LIST_PATH).catch(() => null)
  const reportTokens = filterChain138Tokens(Array.isArray(reportResult?.tokens) ? reportResult.tokens : [], chainId)
  if (reportTokens.length > 0) {
    return { tokens: reportTokens, source: 'report' }
  }

  const configResult = await fetchPublicJson<{ tokens?: TokenListToken[] }>(CONFIG_TOKEN_LIST_PATH).catch(() => null)
  return {
    tokens: filterChain138Tokens(Array.isArray(configResult?.tokens) ? configResult.tokens : [], chainId),
    source: 'config',
  }
}

export function resolveTokenListClientPath(surface: TokenListSurface, chainId = 138): string {
  return surface === 'extended' ? CONFIG_TOKEN_LIST_PATH : `/api/v1/report/token-list?chainId=${chainId}`
}

export async function loadTokenListResponseForSurface(
  surface: TokenListSurface,
  chainId = 138,
): Promise<{ response: { tokens: TokenListToken[] }; source: 'report' | 'config'; label: string }> {
  const { tokens, source } = await fetchTokenListForSurface(surface, chainId)
  return {
    response: { tokens },
    source,
    label: TOKEN_LIST_SURFACE_LABELS[surface],
  }
}
