export const CHAIN138_ID = 138

export const CURATED_FEATURED_SYMBOLS = ['cUSDT', 'cUSDC', 'cXAUC', 'cXAUT', 'cEURT', 'USDT'] as const
export const WALLET_FEATURED_SYMBOLS = ['cUSDT', 'cUSDC', 'USDT', 'USDC', 'cXAUC', 'cXAUT'] as const
export const HOME_EXTRA_PRICE_SYMBOLS = ['WETH'] as const

export const FALLBACK_HOME_PRICE_FEED_ADDRESSES = [
  '0x93E66202A11B1772E55407B32B44e5Cd8eda7f22',
  '0xf22258f57794CC8E06237084b353Ab30fFfa640b',
  '0x290E52a8819A4fBd0714E517225429AA2B70EC6b',
  '0xc02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
] as const

export const HOME_DASHBOARD_REFRESH_MS = 60_000
export const HOME_PRICE_FEED_REFRESH_MS = 60_000
export const WALLET_SNAPSHOT_REFRESH_MS = 60_000

export interface FeaturedTokenCandidate {
  chainId?: number
  symbol?: string
  address?: string
  name?: string
  decimals?: number
  logoURI?: string
  tags?: string[]
  extensions?: Record<string, unknown>
}

function normalizeSymbol(symbol?: string): string {
  return (symbol || '').trim()
}

function normalizeAddressKey(address?: string): string {
  return (address || '').trim().toLowerCase()
}

function isValidAddress(address?: string): address is string {
  return typeof address === 'string' && /^0x[a-fA-F0-9]{40}$/.test(address.trim())
}

export function isStagedFeaturedToken(token: FeaturedTokenCandidate): boolean {
  const extensions = token.extensions || {}
  const deploymentVersion = String(extensions.deploymentVersion || '').toLowerCase()
  const deploymentStatus = String(extensions.deploymentStatus || '').toLowerCase()
  return deploymentVersion === 'v2' || deploymentStatus === 'staged'
}

export function featuredTokenRank(
  token: FeaturedTokenCandidate,
  curatedAddressKeys?: ReadonlySet<string>,
): number {
  let rank = 0
  if (isStagedFeaturedToken(token)) rank += 100
  const addressKey = normalizeAddressKey(token.address)
  if (curatedAddressKeys && addressKey && !curatedAddressKeys.has(addressKey)) {
    rank += 10
  }
  return rank
}

export function pickBestTokenForSymbol(
  tokens: FeaturedTokenCandidate[],
  symbol: string,
  options?: { chainId?: number; curatedAddressKeys?: ReadonlySet<string> },
): FeaturedTokenCandidate | null {
  const chainId = options?.chainId ?? CHAIN138_ID
  const normalizedSymbol = normalizeSymbol(symbol)
  const matches = tokens.filter(
    (token) =>
      token.chainId === chainId &&
      normalizeSymbol(token.symbol) === normalizedSymbol &&
      isValidAddress(token.address),
  )

  if (matches.length === 0) return null

  return [...matches].sort(
    (left, right) =>
      featuredTokenRank(left, options?.curatedAddressKeys) -
      featuredTokenRank(right, options?.curatedAddressKeys),
  )[0]
}

export function selectFeaturedTokensBySymbol(
  tokens: FeaturedTokenCandidate[],
  preferredSymbols: readonly string[],
  options?: { chainId?: number; limit?: number; curatedAddressKeys?: ReadonlySet<string> },
): FeaturedTokenCandidate[] {
  const selected = preferredSymbols
    .map((symbol) => pickBestTokenForSymbol(tokens, symbol, options))
    .filter((token): token is FeaturedTokenCandidate & { address: string } => Boolean(token?.address))

  const deduped: FeaturedTokenCandidate[] = []
  const seen = new Set<string>()
  for (const token of selected) {
    const key = normalizeAddressKey(token.address)
    if (seen.has(key)) continue
    seen.add(key)
    deduped.push(token)
  }

  if (deduped.length > 0) {
    return options?.limit ? deduped.slice(0, options.limit) : deduped
  }

  const fallback = tokens
    .filter((token) => (options?.chainId ?? CHAIN138_ID) === token.chainId && isValidAddress(token.address))
    .sort(
      (left, right) =>
        featuredTokenRank(left, options?.curatedAddressKeys) -
        featuredTokenRank(right, options?.curatedAddressKeys),
    )

  return options?.limit ? fallback.slice(0, options.limit) : fallback.slice(0, 6)
}

export function buildCuratedAddressKeys(tokens: FeaturedTokenCandidate[]): Set<string> {
  return new Set(
    tokens
      .filter((token) => token.chainId === CHAIN138_ID && isValidAddress(token.address))
      .map((token) => normalizeAddressKey(token.address)),
  )
}

export function selectCuratedFeaturedTokens(curatedTokens: FeaturedTokenCandidate[]): FeaturedTokenCandidate[] {
  return selectFeaturedTokensBySymbol(curatedTokens, CURATED_FEATURED_SYMBOLS, { chainId: CHAIN138_ID })
}

export function selectWalletFeaturedTokens(
  catalogTokens: FeaturedTokenCandidate[],
  curatedTokens: FeaturedTokenCandidate[] = [],
): FeaturedTokenCandidate[] {
  const curatedAddressKeys = buildCuratedAddressKeys(curatedTokens)
  return selectFeaturedTokensBySymbol(catalogTokens, WALLET_FEATURED_SYMBOLS, {
    chainId: CHAIN138_ID,
    curatedAddressKeys: curatedAddressKeys.size > 0 ? curatedAddressKeys : undefined,
  })
}

export function selectHomePriceFeedTokens(
  curatedTokens: FeaturedTokenCandidate[],
  reportTokens: FeaturedTokenCandidate[] = [],
): FeaturedTokenCandidate[] {
  const curatedAddressKeys = buildCuratedAddressKeys(curatedTokens)
  const pool = reportTokens.length > 0 ? reportTokens : curatedTokens
  return selectFeaturedTokensBySymbol(pool, [...CURATED_FEATURED_SYMBOLS, ...HOME_EXTRA_PRICE_SYMBOLS], {
    chainId: CHAIN138_ID,
    curatedAddressKeys: curatedAddressKeys.size > 0 ? curatedAddressKeys : undefined,
  })
}

export function resolveHomePriceFeedAddresses(
  curatedTokens: FeaturedTokenCandidate[],
  reportTokens: FeaturedTokenCandidate[] = [],
): string[] {
  const fromCatalog = selectHomePriceFeedTokens(curatedTokens, reportTokens)
    .map((token) => token.address)
    .filter(isValidAddress)

  if (fromCatalog.length > 0) return fromCatalog
  return [...FALLBACK_HOME_PRICE_FEED_ADDRESSES]
}
