import { buildAccountListRelayUrlsForMerge } from '@/lib/account-list-relay-urls'
import { createInterestListDraftEvent } from '@/lib/draft-event'
import { normalizeTopic } from '@/lib/discussion-topics'
import { fetchLatestReplaceableListEvent } from '@/lib/replaceable-list-latest'
import logger from '@/lib/logger'
import client from '@/services/client.service'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'
import { useNostr } from '@/providers/nostr-context'
import { useFavoriteRelays } from './FavoriteRelaysProvider'
import { InterestListContext } from './interest-list-context'

export function InterestListProvider({ children }: { children: React.ReactNode }) {
  const { t } = useTranslation()
  const { pubkey: accountPubkey, interestListEvent, publish, updateInterestListEvent } = useNostr()
  const { favoriteRelays, blockedRelays } = useFavoriteRelays()
  const [topics, setTopics] = useState<string[]>([])
  const subscribedTopics = useMemo(() => new Set(topics), [topics])
  const [changing, setChanging] = useState(false)

  const INTEREST_LIST_KIND = 10015

  const buildComprehensiveRelayList = useCallback(async () => {
    if (!accountPubkey) return [] as string[]
    return buildAccountListRelayUrlsForMerge({
      accountPubkey,
      favoriteRelays: favoriteRelays ?? [],
      blockedRelays
    })
  }, [accountPubkey, favoriteRelays, blockedRelays])

  useEffect(() => {
    const updateTopics = () => {
      if (!interestListEvent) {
        setTopics([])
        return
      }

      // Extract t-tags from the interest list
      const topicTags = interestListEvent.tags
        .filter(tag => tag[0] === 't' && tag[1])
        .map(tag => normalizeTopic(tag[1]))
      
      setTopics(topicTags)
    }
    updateTopics()
  }, [interestListEvent])

  const getSubscribedTopics = useCallback(() => {
    return Array.from(subscribedTopics)
  }, [subscribedTopics])

  const isSubscribed = useCallback(
    (topic: string): boolean => {
      return subscribedTopics.has(normalizeTopic(topic))
    },
    [subscribedTopics]
  )

  const publishNewInterestListEvent = async (newTopics: string[]) => {
    const newInterestListEvent = createInterestListDraftEvent(newTopics)
    
    // Use the same comprehensive relay list as pins for publishing
    const comprehensiveRelays = await buildComprehensiveRelayList()
    logger.component('InterestListProvider', 'Publishing to comprehensive relays', { count: comprehensiveRelays.length })
    
    const publishedEvent = await publish(newInterestListEvent, {
      specifiedRelayUrls: comprehensiveRelays
    })
    return publishedEvent
  }

  const subscribe = async (topic: string) => {
    logger.component('InterestListProvider', 'subscribe called', { topic, accountPubkey, changing })
    if (!accountPubkey || changing) return

    const normalizedTopic = normalizeTopic(topic)
    if (subscribedTopics.has(normalizedTopic)) {
      logger.component('InterestListProvider', 'Already subscribed to topic')
      return
    }

    setChanging(true)
    try {
      logger.component('InterestListProvider', 'Fetching existing interest list event')
      const relays = await buildComprehensiveRelayList()
      let interestListEvent =
        (await fetchLatestReplaceableListEvent(accountPubkey, INTEREST_LIST_KIND, relays)) ?? null
      if (!interestListEvent) {
        interestListEvent = (await client.fetchInterestListEvent(accountPubkey)) ?? null
      }
      logger.component('InterestListProvider', 'Existing interest list event', { hasEvent: !!interestListEvent })
      
      const currentTopics = interestListEvent
        ? interestListEvent.tags
            .filter((tag: string[]) => tag[0] === 't' && tag[1])
            .map((tag: string[]) => normalizeTopic(tag[1]))
        : []

      logger.component('InterestListProvider', 'Current topics', { topics: currentTopics })

      if (currentTopics.includes(normalizedTopic)) {
        logger.component('InterestListProvider', 'Already subscribed to topic (from event)')
        return
      }

      const newTopics = Array.from(new Set([...currentTopics, normalizedTopic]))
      logger.component('InterestListProvider', 'Creating new interest list with topics', { topics: newTopics })
      
      const newInterestListEvent = await publishNewInterestListEvent(newTopics)
      logger.component('InterestListProvider', 'Published new interest list event', { hasEvent: !!newInterestListEvent })
      
      await updateInterestListEvent(newInterestListEvent)
      logger.component('InterestListProvider', 'Updated interest list event in state')
      
      toast.success(t('Subscribed to topic'))
    } catch (error) {
      logger.component('InterestListProvider', 'Failed to publish interest list event', { error: (error as Error).message })
      // Even if publishing fails, the subscription worked locally, so show success
      // The user can still see their hashtag feed working
      toast.success(t('Subscribed to topic (local)'))
    } finally {
      setChanging(false)
    }
  }

  const unsubscribe = async (topic: string) => {
    if (!accountPubkey || changing) return

    const normalizedTopic = normalizeTopic(topic)
    if (!subscribedTopics.has(normalizedTopic)) {
      return
    }

    setChanging(true)
    try {
      const relays = await buildComprehensiveRelayList()
      let interestListEvent =
        (await fetchLatestReplaceableListEvent(accountPubkey, INTEREST_LIST_KIND, relays)) ?? null
      if (!interestListEvent) {
        interestListEvent = (await client.fetchInterestListEvent(accountPubkey)) ?? null
      }
      if (!interestListEvent) return

      const currentTopics = interestListEvent.tags
        .filter((tag: string[]) => tag[0] === 't' && tag[1])
        .map((tag: string[]) => normalizeTopic(tag[1]))

      const newTopics = currentTopics.filter((t: string) => t !== normalizedTopic)
      
      if (newTopics.length === currentTopics.length) {
        // Topic wasn't in the list
        return
      }

      const newInterestListEvent = await publishNewInterestListEvent(newTopics)
      await updateInterestListEvent(newInterestListEvent)
      
      toast.success(t('Unsubscribed from topic'))
    } catch (error) {
      logger.component('InterestListProvider', 'Failed to unsubscribe from topic', { error: (error as Error).message })
      toast.error(t('Failed to unsubscribe from topic') + ': ' + (error as Error).message)
    } finally {
      setChanging(false)
    }
  }

  return (
    <InterestListContext.Provider
      value={{
        subscribedTopics,
        changing,
        isSubscribed,
        subscribe,
        unsubscribe,
        getSubscribedTopics
      }}
    >
      {children}
    </InterestListContext.Provider>
  )
}

