import { getExplorerApiBase } from './blockscout'

export interface RouteMatrixLeg {
  protocol?: string
  executor?: string
  poolAddress?: string
}

export interface RouteMatrixRoute {
  routeId: string
  status?: string
  label?: string
  routeType?: string
  fromChainId?: number
  toChainId?: number
  tokenInSymbol?: string
  tokenOutSymbol?: string
  assetSymbol?: string
  hopCount?: number
  aggregatorFamilies?: string[]
  notes?: string[]
  reason?: string
  tokenInSymbols?: string[]
  legs?: RouteMatrixLeg[]
}

export interface RouteMatrixCounts {
  liveSwapRoutes?: number
  liveBridgeRoutes?: number
  blockedOrPlannedRoutes?: number
  filteredLiveRoutes?: number
}

export interface RouteMatrixResponse {
  generatedAt?: string
  updated?: string
  version?: string
  homeChainId?: number
  liveRoutes?: RouteMatrixRoute[]
  blockedOrPlannedRoutes?: RouteMatrixRoute[]
  counts?: RouteMatrixCounts
}

export interface ExplorerNetwork {
  chainIdDecimal?: number
  chainName?: string
  shortName?: string
}

export interface NetworksResponse {
  version?: string
  source?: string
  lastModified?: string
  networks?: ExplorerNetwork[]
}

export interface MissionControlLiquidityPool {
  address: string
  dex?: string
  token0?: {
    symbol?: string
  }
  token1?: {
    symbol?: string
  }
  tvl?: number
}

export interface MissionControlLiquidityPoolsResponse {
  count?: number
  pools?: MissionControlLiquidityPool[]
}

interface RawMissionControlLiquidityPoolsResponse {
  count?: number
  pools?: MissionControlLiquidityPool[]
  data?: {
    count?: number
    pools?: MissionControlLiquidityPool[]
  }
}

export function normalizeMissionControlLiquidityPools(
  raw: RawMissionControlLiquidityPoolsResponse | null | undefined
): MissionControlLiquidityPoolsResponse {
  if (!raw) {
    return { count: 0, pools: [] }
  }

  const nested = raw.data
  const pools = Array.isArray(raw.pools)
    ? raw.pools
    : Array.isArray(nested?.pools)
      ? nested.pools
      : []

  const count = typeof raw.count === 'number'
    ? raw.count
    : typeof nested?.count === 'number'
      ? nested.count
      : pools.length

  return { count, pools }
}

const tokenAggregationBase = `${getExplorerApiBase()}/token-aggregation/api/v1`
const missionControlBase = `${getExplorerApiBase()}/explorer-api/v1/mission-control`

async function fetchJson<T>(url: string): Promise<T> {
  const response = await fetch(url)
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`)
  }
  return (await response.json()) as T
}

export const routesApi = {
  getNetworks: async (): Promise<NetworksResponse> =>
    fetchJson<NetworksResponse>(`${tokenAggregationBase}/networks`),

  getRouteMatrix: async (): Promise<RouteMatrixResponse> =>
    fetchJson<RouteMatrixResponse>(`${tokenAggregationBase}/routes/matrix?includeNonLive=true`),

  getTokenPools: async (tokenAddress: string): Promise<MissionControlLiquidityPoolsResponse> =>
    normalizeMissionControlLiquidityPools(
      await fetchJson<RawMissionControlLiquidityPoolsResponse>(
        `${missionControlBase}/liquidity/token/${tokenAddress}/pools`
      )
    ),
}
