import { getExplorerApiBase } from './blockscout'
import type { ExplorerFreshnessDiagnostics } from './stats'

export interface MissionControlRelaySummary {
  text: string
  tone: 'normal' | 'warning' | 'danger'
  items: MissionControlRelayItemSummary[]
}

export interface MissionControlRelayItemSummary {
  key: string
  label: string
  status: string
  text: string
  tone: 'normal' | 'warning' | 'danger'
}

export interface MissionControlRelaySnapshot {
  status?: string
  last_error?: {
    scope?: string
    message?: string
    message_id?: string
    target_bridge?: string
    token?: string
    available_amount?: string
    required_amount?: string
    shortfall?: string
  }
  monitoring?: {
    delivery_enabled?: boolean
    shedding?: boolean
  }
  service?: {
    profile?: string
  }
  source?: {
    chain_name?: string
    bridge_filter?: string
  }
  destination?: {
    chain_name?: string
    relay_bridge?: string
    relay_bridge_default?: string
  }
  queue?: {
    size?: number
    processed?: number
    failed?: number
  }
  last_source_poll?: {
    at?: string
    ok?: boolean
    logs_fetched?: number
  }
}

export interface MissionControlRelayProbe {
  ok?: boolean
  body?: MissionControlRelaySnapshot
}

export interface MissionControlRelayPayload {
  url_probe?: MissionControlRelayProbe
  file_snapshot?: MissionControlRelaySnapshot
  file_snapshot_error?: string
}

export interface MissionControlChainStatus {
  status?: string
  name?: string
  head_age_sec?: number
  latency_ms?: number
  block_number?: string
}

export interface MissionControlMode {
  kind?: string | null
  updated_at?: string | null
  age_seconds?: number | null
  reason?: string | null
  scope?: string | null
  source?: string | null
  confidence?: string | null
  provenance?: string | null
}

export interface MissionControlSubsystemStatus {
  status?: string | null
  updated_at?: string | null
  age_seconds?: number | null
  source?: string | null
  confidence?: string | null
  provenance?: string | null
  completeness?: string | null
}

export interface MissionControlBridgeStatusResponse {
  data?: {
    status?: string
    checked_at?: string
    freshness?: unknown
    diagnostics?: ExplorerFreshnessDiagnostics | null
    sampling?: {
      stats_generated_at?: string | null
      rpc_probe_at?: string | null
      stats_window_seconds?: number | null
      issues?: Record<string, string> | null
    }
    mode?: MissionControlMode
    subsystems?: Record<string, MissionControlSubsystemStatus>
    chains?: Record<string, MissionControlChainStatus>
    ccip_relay?: MissionControlRelayPayload
    ccip_relays?: Record<string, MissionControlRelayPayload>
  }
}

const missionControlRelayLabels: Record<string, string> = {
  mainnet: 'Mainnet',
  mainnet_weth: 'Mainnet WETH',
  mainnet_cw: 'Mainnet cW',
  bsc: 'BSC',
  avax: 'Avalanche',
  avalanche: 'Avalanche',
  avax_cw: 'Avalanche cW',
  avax_to_138: 'Avalanche -> 138',
}

function getMissionControlStreamUrl(): string {
  return `${getExplorerApiBase()}/explorer-api/v1/mission-control/stream`
}

function getMissionControlBridgeStatusUrl(): string {
  return `${getExplorerApiBase()}/explorer-api/v1/track1/bridge/status`
}

function relativeAge(isoString?: string): string {
  if (!isoString) return ''
  const parsed = Date.parse(isoString)
  if (!Number.isFinite(parsed)) return ''
  const seconds = Math.max(0, Math.round((Date.now() - parsed) / 1000))
  if (seconds < 60) return `${seconds}s ago`
  const minutes = Math.round(seconds / 60)
  if (minutes < 60) return `${minutes}m ago`
  const hours = Math.round(minutes / 60)
  return `${hours}h ago`
}

function describeRelayStatus(snapshot: MissionControlRelaySnapshot, status: string): string {
  if (snapshot.last_error?.scope === 'bridge_inventory') {
    return snapshot.queue?.size && snapshot.queue.size > 0
      ? 'underfunded queued release'
      : 'underfunded release'
  }
  if (snapshot.last_error?.scope === 'bridge_inventory_probe') {
    return snapshot.queue?.size && snapshot.queue.size > 0
      ? 'inventory check deferred'
      : 'inventory check pending'
  }
  if (status === 'paused' && snapshot.monitoring?.delivery_enabled === false) {
    return snapshot.queue?.size && snapshot.queue.size > 0 ? 'delivery paused (queueing)' : 'delivery paused'
  }
  if (status === 'paused' && snapshot.monitoring?.shedding) {
    return 'paused (shedding)'
  }
  return status
}

export function summarizeMissionControlRelay(
  response: MissionControlBridgeStatusResponse | null | undefined
): MissionControlRelaySummary | null {
  const relays = getMissionControlRelays(response)
  if (!relays) return null

  const items = Object.entries(relays)
    .map(([key, relay]): MissionControlRelayItemSummary | null => {
      const label = getMissionControlRelayLabel(key)

      if (relay.url_probe && relay.url_probe.ok === false) {
        return {
          key,
          label,
          status: 'down',
          text: `${label}: probe failed`,
          tone: 'danger',
        }
      }

      if (relay.file_snapshot_error) {
        return {
          key,
          label,
          status: 'snapshot-error',
          text: `${label}: snapshot error`,
          tone: 'danger',
        }
      }

      const snapshot = relay.url_probe?.body || relay.file_snapshot
      if (!snapshot) {
        return {
          key,
          label,
          status: 'configured',
          text: `${label}: probe configured`,
          tone: 'normal',
        }
      }

      const status = String(snapshot.status || 'unknown').toLowerCase()
      const statusLabel = describeRelayStatus(snapshot, status)
      const destination = snapshot.destination?.chain_name
      const queueSize = snapshot.queue?.size
      const pollAge = relativeAge(snapshot.last_source_poll?.at)

      let text = `${label}: ${statusLabel}`
      if (destination) text += ` -> ${destination}`
      if (queueSize != null) text += ` · queue ${queueSize}`
      if (pollAge) text += ` · polled ${pollAge}`

      let tone: MissionControlRelaySummary['tone'] = 'normal'
      if (['paused', 'starting'].includes(status)) {
        tone = 'warning'
      }
      if (['degraded', 'stale', 'stopped', 'down'].includes(status)) {
        tone = 'danger'
      }

      return { key, label, status, text, tone }
    })
    .filter((item): item is MissionControlRelayItemSummary => item !== null)

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

  const tone: MissionControlRelaySummary['tone'] = items.some((item) => item.tone === 'danger')
    ? 'danger'
    : items.some((item) => item.tone === 'warning')
      ? 'warning'
      : 'normal'

  const text =
    items.length === 1
      ? items[0].text
      : tone === 'normal'
        ? `${items.length} relay lanes operational`
        : `Relay lanes need attention`

  return { text, tone, items }
}

export function getMissionControlRelays(
  response: MissionControlBridgeStatusResponse | null | undefined
): Record<string, MissionControlRelayPayload> | null {
  return response?.data?.ccip_relays && Object.keys(response.data.ccip_relays).length > 0
    ? response.data.ccip_relays
    : response?.data?.ccip_relay
      ? { mainnet: response.data.ccip_relay }
      : null
}

export function getMissionControlRelayLabel(key: string): string {
  return missionControlRelayLabels[key] || key.toUpperCase()
}

export const missionControlApi = {
  getBridgeStatus: async (): Promise<MissionControlBridgeStatusResponse> => {
    const response = await fetch(getMissionControlBridgeStatusUrl())
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`)
    }
    return (await response.json()) as MissionControlBridgeStatusResponse
  },

  subscribeBridgeStatus: (
    onStatus: (status: MissionControlBridgeStatusResponse) => void,
    onError?: (error: unknown) => void
  ): (() => void) => {
    if (typeof window === 'undefined' || typeof window.EventSource === 'undefined') {
      onError?.(new Error('EventSource is not available in this environment'))
      return () => {}
    }

    const eventSource = new window.EventSource(getMissionControlStreamUrl())

    const handleMessage = (event: MessageEvent<string>) => {
      try {
        const payload = JSON.parse(event.data) as MissionControlBridgeStatusResponse
        onStatus(payload)
      } catch (error) {
        onError?.(error)
      }
    }

    eventSource.addEventListener('mission-control', handleMessage)
    eventSource.onmessage = handleMessage

    eventSource.onerror = () => {
      onError?.(new Error('Mission-control live stream connection lost'))
    }

    return () => {
      eventSource.removeEventListener('mission-control', handleMessage)
      eventSource.close()
    }
  },
}
