import type { Block } from './blocks'
import type { Transaction } from './transactions'
import type { TransactionSummary } from './addresses'

export function getExplorerApiBase() {
  return (process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080').replace(/\/$/, '')
}

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

type HashLike = string | { hash?: string | null } | null | undefined

export function extractHash(value: HashLike): string {
  if (!value) return ''
  return typeof value === 'string' ? value : value.hash || ''
}

function toNumber(value: unknown): number {
  if (typeof value === 'number') return value
  if (typeof value === 'string' && value.trim() !== '') return Number(value)
  return 0
}

interface BlockscoutBlock {
  hash: string
  height: number | string
  timestamp: string
  miner: HashLike
  transaction_count: number | string
  gas_used: number | string
  gas_limit: number | string
}

interface BlockscoutTransaction {
  hash: string
  block_number: number | string
  from: HashLike
  to: HashLike
  value: string
  status?: string | null
  result?: string | null
  gas_price?: number | string | null
  gas_limit: number | string
  gas_used?: number | string | null
  max_fee_per_gas?: number | string | null
  max_priority_fee_per_gas?: number | string | null
  raw_input?: string | null
  timestamp: string
  created_contract?: HashLike
}

function normalizeStatus(raw: BlockscoutTransaction): number {
  const value = (raw.status || raw.result || '').toString().toLowerCase()
  if (value === 'success' || value === 'ok' || value === '1') return 1
  if (value === 'error' || value === 'failed' || value === '0') return 0
  return 0
}

export function normalizeBlock(raw: BlockscoutBlock, chainId: number): Block {
  return {
    chain_id: chainId,
    number: toNumber(raw.height),
    hash: raw.hash,
    timestamp: raw.timestamp,
    miner: extractHash(raw.miner),
    transaction_count: toNumber(raw.transaction_count),
    gas_used: toNumber(raw.gas_used),
    gas_limit: toNumber(raw.gas_limit),
  }
}

export function normalizeTransaction(raw: BlockscoutTransaction, chainId: number): Transaction {
  return {
    chain_id: chainId,
    hash: raw.hash,
    block_number: toNumber(raw.block_number),
    block_hash: '',
    transaction_index: 0,
    from_address: extractHash(raw.from),
    to_address: extractHash(raw.to) || undefined,
    value: raw.value || '0',
    gas_price: raw.gas_price != null ? toNumber(raw.gas_price) : undefined,
    max_fee_per_gas: raw.max_fee_per_gas != null ? toNumber(raw.max_fee_per_gas) : undefined,
    max_priority_fee_per_gas: raw.max_priority_fee_per_gas != null ? toNumber(raw.max_priority_fee_per_gas) : undefined,
    gas_limit: toNumber(raw.gas_limit),
    gas_used: raw.gas_used != null ? toNumber(raw.gas_used) : undefined,
    status: normalizeStatus(raw),
    input_data: raw.raw_input || undefined,
    contract_address: extractHash(raw.created_contract) || undefined,
    created_at: raw.timestamp,
  }
}

export function normalizeTransactionSummary(raw: BlockscoutTransaction): TransactionSummary {
  return {
    hash: raw.hash,
    block_number: toNumber(raw.block_number),
    from_address: extractHash(raw.from),
    to_address: extractHash(raw.to) || undefined,
    value: raw.value || '0',
    status: normalizeStatus(raw),
  }
}
