import NormalFeed from '@/components/NormalFeed'
import type { TNoteListRef } from '@/components/NoteList'
import { checkAlgoRelay } from '@/lib/relay'
import { normalizeUrl } from '@/lib/url'
import { useFeed } from '@/providers/feed-context'
import { useKindFilterOrDefaults } from '@/providers/KindFilterProvider'
import relayInfoService from '@/services/relay-info.service'
import { kinds } from 'nostr-tools'
import React, { forwardRef, useEffect, useMemo, useState } from 'react'

const RelaysFeed = forwardRef<
  TNoteListRef,
  {
    setSubHeader?: (node: React.ReactNode) => void
    onSubHeaderRefresh?: () => void
    /** When set, subscription kinds (fixed list); otherwise uses KindFilterProvider. */
    kindsOverride?: number[]
  }
>(function RelaysFeed({ setSubHeader, onSubHeaderRefresh, kindsOverride }, ref) {
  const { relayUrls, replyRelayUrls } = useFeed()
  const { showKinds } = useKindFilterOrDefaults()
  const [areAlgoRelays, setAreAlgoRelays] = useState(false)

  const relayUrlsKey = useMemo(
    () =>
      [...relayUrls]
        .map((u) => normalizeUrl(u) || u)
        .filter(Boolean)
        .sort()
        .join('|'),
    [relayUrls]
  )
  const replyRelayUrlsKey = useMemo(
    () =>
      [...replyRelayUrls]
        .map((u) => normalizeUrl(u) || u)
        .filter(Boolean)
        .sort()
        .join('|'),
    [replyRelayUrls]
  )
  const homeFeedSeenOnAllowlistOp = useMemo(() => relayUrls, [relayUrlsKey])
  const homeFeedSeenOnAllowlistReplies = useMemo(() => replyRelayUrls, [replyRelayUrlsKey])

  useEffect(() => {
    if (relayUrls.length === 0) {
      setAreAlgoRelays(false)
      return
    }
    let cancelled = false

    const init = async () => {
      const timeoutPromise = new Promise<never>((_, reject) => {
        setTimeout(() => {
          reject(new Error('getRelayInfos timeout after 8 seconds'))
        }, 8000)
      })

      try {
        const relayInfos = await Promise.race([
          relayInfoService.getRelayInfos(relayUrls),
          timeoutPromise
        ])
        if (cancelled) return
        const areAlgo = relayInfos.every((relayInfo) => checkAlgoRelay(relayInfo))
        setAreAlgoRelays(areAlgo)
      } catch {
        if (!cancelled) setAreAlgoRelays(false)
      }
    }

    void init()
    return () => {
      cancelled = true
    }
  }, [relayUrlsKey, relayUrls.length])

  /** Stable identity when kind filter is empty so `subRequests` does not invalidate every render. */
  const fallbackNoteKinds = useMemo(() => [kinds.ShortTextNote], [])
  const defaultKinds = useMemo(() => {
    if (kindsOverride && kindsOverride.length > 0) return kindsOverride
    if (showKinds.length > 0) return showKinds
    return fallbackNoteKinds
  }, [kindsOverride, showKinds, fallbackNoteKinds])

  const canRenderFeed = relayUrls.length > 0

  // Hooks must run every render — never place useMemo after conditional returns.
  const subRequests = useMemo(() => {
    if (!canRenderFeed) return []
    return [
      {
        urls: relayUrls,
        filter: {
          kinds: defaultKinds
        }
      }
    ]
  }, [canRenderFeed, relayUrlsKey, relayUrls, defaultKinds])
  const repliesSubRequests = useMemo(() => {
    if (!canRenderFeed) return []
    return [
      {
        urls: replyRelayUrls.length > 0 ? replyRelayUrls : relayUrls,
        filter: {
          kinds: defaultKinds
        }
      }
    ]
  }, [canRenderFeed, replyRelayUrlsKey, replyRelayUrls, relayUrlsKey, relayUrls, defaultKinds])

  if (!canRenderFeed) {
    return null
  }

  // preserveTimeline: merge when relay list grows (e.g. all-favorites list fills in).
  return (
    <NormalFeed
      ref={ref}
      subRequests={subRequests}
      areAlgoRelays={areAlgoRelays}
      isMainFeed
      setSubHeader={setSubHeader}
      onSubHeaderRefresh={onSubHeaderRefresh}
      preserveTimelineOnSubRequestsChange
      repliesSubRequests={repliesSubRequests}
      mainFeedGalleryRelayUrls={replyRelayUrls}
      widenMainGalleryRelays={false}
      feedSubscriptionKey="home-all-favorites"
      feedTimelineScopeKey="all-favorites"
      homeFeedSeenOnAllowlistOp={homeFeedSeenOnAllowlistOp}
      homeFeedSeenOnAllowlistReplies={homeFeedSeenOnAllowlistReplies}
      showFeedClientFilter
      hostPrimaryPageName="feed"
    />
  )
})

RelaysFeed.displayName = 'RelaysFeed'
export default RelaysFeed
