'use client'

import { useEffect, useMemo, useState } from 'react'

import type { AwoooPStatusChain } from '@/components/awooop/status-chain'
import { API_V1_URL } from '@/lib/config'

interface UseIncidentStatusChainsOptions {
  incidentIds: string[]
  limit?: number
  concurrency?: number
  projectId?: string
  refreshKey?: string | number | Date | null
  timeoutMs?: number
}

interface UseIncidentStatusChainsResult {
  statusChains: Record<string, AwoooPStatusChain | null>
  requestedIncidentIds: string[]
  isLoading: boolean
}

export function useIncidentStatusChains({
  incidentIds,
  limit = 25,
  concurrency = 4,
  projectId = 'awoooi',
  refreshKey = null,
  timeoutMs = 12000,
}: UseIncidentStatusChainsOptions): UseIncidentStatusChainsResult {
  const incidentIdsKey = incidentIds.filter(Boolean).join('|')
  const requestedIncidentIds = useMemo(() => {
    return Array.from(new Set(incidentIdsKey ? incidentIdsKey.split('|') : [])).slice(0, limit)
  }, [incidentIdsKey, limit])
  const incidentKey = requestedIncidentIds.join('|')
  const [statusChains, setStatusChains] = useState<Record<string, AwoooPStatusChain | null>>({})
  const [isLoading, setIsLoading] = useState(false)

  useEffect(() => {
    if (requestedIncidentIds.length === 0) {
      setStatusChains({})
      setIsLoading(false)
      return
    }

    let active = true
    const controller = new AbortController()
    const timeout = window.setTimeout(() => controller.abort(), timeoutMs)
    const requestConcurrency = Math.max(1, Math.min(concurrency, requestedIncidentIds.length))
    let nextIndex = 0
    let activeRequests = 0
    let completedRequests = 0
    setIsLoading(true)
    setStatusChains(Object.fromEntries(requestedIncidentIds.map(incidentId => [incidentId, null])))

    const fetchStatusChain = async (incidentId: string): Promise<AwoooPStatusChain | null> => {
      const params = new URLSearchParams({ project_id: projectId, incident_id: incidentId })
      try {
        const response = await fetch(`${API_V1_URL}/platform/status-chain?${params.toString()}`, {
          cache: 'no-store',
          signal: controller.signal,
        })
        if (!response.ok) return null
        return await response.json() as AwoooPStatusChain
      } catch {
        return null
      }
    }

    const finish = () => {
      completedRequests += 1
      if (completedRequests >= requestedIncidentIds.length) {
        window.clearTimeout(timeout)
        if (active) setIsLoading(false)
      }
    }

    const pump = () => {
      if (!active) return
      while (activeRequests < requestConcurrency && nextIndex < requestedIncidentIds.length) {
        const incidentId = requestedIncidentIds[nextIndex]
        nextIndex += 1
        activeRequests += 1
        fetchStatusChain(incidentId)
          .then(statusChain => {
            if (active) {
              setStatusChains(previous => ({ ...previous, [incidentId]: statusChain }))
            }
          })
          .finally(() => {
            activeRequests -= 1
            finish()
            pump()
          })
      }
    }

    pump()

    return () => {
      active = false
      window.clearTimeout(timeout)
      controller.abort()
    }
  }, [concurrency, incidentKey, projectId, requestedIncidentIds, refreshKey, timeoutMs])

  return { statusChains, requestedIncidentIds, isLoading }
}

export type { UseIncidentStatusChainsOptions, UseIncidentStatusChainsResult }
