import { ApiResponse } from './client'
import { fetchBlockscoutJson, normalizeTransactionSummary } from './blockscout'

export interface AddressInfo {
  address: string
  chain_id: number
  transaction_count: number
  token_count: number
  is_contract: boolean
  label?: string
  tags: string[]
}

export interface AddressTransactionsParams {
  chain_id: number
  from_address: string
  page?: number
  page_size?: number
}

export interface TransactionSummary {
  hash: string
  block_number: number
  from_address: string
  to_address?: string
  value: string
  status?: number
}

export const addressesApi = {
  get: async (chainId: number, address: string): Promise<ApiResponse<AddressInfo>> => {
    const [raw, counters] = await Promise.all([
      fetchBlockscoutJson<{
        hash: string
        is_contract: boolean
        name?: string | null
        token?: { symbol?: string | null } | null
        public_tags?: Array<{ label?: string; display_name?: string; name?: string } | string>
        private_tags?: Array<{ label?: string; display_name?: string; name?: string } | string>
        watchlist_names?: string[]
      }>(`/api/v2/addresses/${address}`),
      fetchBlockscoutJson<{
        transactions_count?: number
        token_balances_count?: number
      }>(`/api/v2/addresses/${address}/tabs-counters`),
    ])

    const tags = [
      ...(raw.public_tags || []),
      ...(raw.private_tags || []),
      ...(raw.watchlist_names || []),
    ]
      .map((tag) => {
        if (typeof tag === 'string') return tag
        return tag.display_name || tag.label || tag.name || ''
      })
      .filter(Boolean)

    return {
      data: {
        address: raw.hash,
        chain_id: chainId,
        transaction_count: Number(counters.transactions_count || 0),
        token_count: Number(counters.token_balances_count || 0),
        is_contract: !!raw.is_contract,
        label: raw.name || raw.token?.symbol || undefined,
        tags,
      },
    }
  },
  /** Use when you need to check response.ok before setting state (avoids treating 4xx/5xx body as data). */
  getSafe: async (chainId: number, address: string): Promise<{ ok: boolean; data: AddressInfo | null }> => {
    try {
      const { data } = await addressesApi.get(chainId, address)
      return { ok: true, data }
    } catch {
      return { ok: false, data: null }
    }
  },
  getTransactionsSafe: async (
    chainId: number,
    address: string,
    page = 1,
    pageSize = 20
  ): Promise<{ ok: boolean; data: TransactionSummary[] }> => {
    try {
      const params = new URLSearchParams({
        page: page.toString(),
        page_size: pageSize.toString(),
      })
      const raw = await fetchBlockscoutJson<{ items?: unknown[] }>(`/api/v2/addresses/${address}/transactions?${params.toString()}`)
      const data = Array.isArray(raw?.items) ? raw.items.map((item) => normalizeTransactionSummary(item as never)) : []
      return { ok: true, data }
    } catch {
      return { ok: false, data: [] }
    }
  },

  getTransactions: async (
    chainId: number,
    address: string,
    page = 1,
    pageSize = 20
  ): Promise<ApiResponse<TransactionSummary[]>> => {
    const params = new URLSearchParams({
      page: page.toString(),
      page_size: pageSize.toString(),
    })
    const raw = await fetchBlockscoutJson<{ items?: unknown[] }>(`/api/v2/addresses/${address}/transactions?${params.toString()}`)
    const data = Array.isArray(raw?.items) ? raw.items.map((item) => normalizeTransactionSummary(item as never)) : []
    return { data }
  },
}
