import { useState, useEffect, useMemo, useCallback } from 'react'
import { useRouter } from 'next/router'
import { useArticles } from '@/hooks/useArticles'
import { useNostrConnect } from '@/hooks/useNostrConnect'
import { useAuthorPresentation } from '@/hooks/useAuthorPresentation'
import { applyFiltersAndSort } from '@/lib/articleFiltering'
import type { Article } from '@/types/nostr'
import type { ArticleFilters } from '@/components/ArticleFilters'
import { HomeView } from '@/components/HomeView'

function usePresentationGuard(connected: boolean, pubkey: string | null) {
  const router = useRouter()
  const { checkPresentationExists } = useAuthorPresentation(pubkey ?? null)

  useEffect(() => {
    const ensurePresentation = async () => {
      if (!connected || !pubkey) {
        return
      }
      const presentation = await checkPresentationExists()
      if (!presentation) {
        await router.push('/presentation')
      }
    }
    void ensurePresentation()
  }, [checkPresentationExists, connected, pubkey, router])
}

function usePresentationArticles(allArticles: Article[]) {
  const [presentationArticles, setPresentationArticles] = useState<Map<string, Article>>(new Map())
  useEffect(() => {
    const presentations = new Map<string, Article>()
    allArticles.forEach((article) => {
      if (article.isPresentation && article.pubkey) {
        presentations.set(article.pubkey, article)
      }
    })
    setPresentationArticles(presentations)
  }, [allArticles])
  return presentationArticles
}

function useHomeState() {
  const [searchQuery, setSearchQuery] = useState('')
  const [selectedCategory, setSelectedCategory] = useState<ArticleFilters['category']>('all')
  const [filters, setFilters] = useState<ArticleFilters>({
    authorPubkey: null,
    minPrice: null,
    maxPrice: null,
    sortBy: 'newest',
    category: 'all',
  })
  const [unlockedArticles, setUnlockedArticles] = useState<Set<string>>(new Set())

  return {
    searchQuery,
    setSearchQuery,
    selectedCategory,
    setSelectedCategory,
    filters,
    setFilters,
    unlockedArticles,
    setUnlockedArticles,
  }
}

function useArticlesData(searchQuery: string) {
  const { articles: allArticlesRaw, allArticles, loading, error, loadArticleContent } = useArticles(searchQuery, null)
  const presentationArticles = usePresentationArticles(allArticles)
  return { allArticlesRaw, allArticles, loading, error, loadArticleContent, presentationArticles }
}

function useCategorySync(selectedCategory: ArticleFilters['category'], setFilters: (value: ArticleFilters | ((prev: ArticleFilters) => ArticleFilters)) => void) {
  useEffect(() => {
    setFilters((prev) => ({
      ...prev,
      category: selectedCategory ?? 'all',
    }))
  }, [selectedCategory, setFilters])
}

function useFilteredArticles(
  allArticlesRaw: Article[],
  searchQuery: string,
  filters: ArticleFilters,
  presentationArticles: Map<string, Article>
) {
  return useMemo(
    () => applyFiltersAndSort(allArticlesRaw, searchQuery, filters, presentationArticles),
    [allArticlesRaw, searchQuery, filters, presentationArticles]
  )
}

function useUnlockHandler(
  loadArticleContent: (id: string, pubkey: string) => Promise<Article | null>,
  setUnlockedArticles: React.Dispatch<React.SetStateAction<Set<string>>>
) {
  return useCallback(
    async (article: Article) => {
      const fullArticle = await loadArticleContent(article.id, article.pubkey)
      if (fullArticle?.paid) {
        setUnlockedArticles((prev) => new Set([...prev, article.id]))
      }
    },
    [loadArticleContent, setUnlockedArticles]
  )
}

function useHomeController() {
  const { connected, pubkey } = useNostrConnect()
  const {
    searchQuery,
    setSearchQuery,
    selectedCategory,
    setSelectedCategory,
    filters,
    setFilters,
    unlockedArticles,
    setUnlockedArticles,
  } = useHomeState()
  const { allArticlesRaw, allArticles, loading, error, loadArticleContent, presentationArticles } =
    useArticlesData(searchQuery)

  usePresentationGuard(connected, pubkey)
  useCategorySync(selectedCategory, setFilters)
  const articles = useFilteredArticles(allArticlesRaw, searchQuery, filters, presentationArticles)
  const handleUnlock = useUnlockHandler(loadArticleContent, setUnlockedArticles)

  return {
    searchQuery,
    setSearchQuery,
    selectedCategory,
    setSelectedCategory,
    filters,
    setFilters,
    articles,
    allArticles,
    loading,
    error,
    unlockedArticles,
    handleUnlock,
  }
}

export default function Home() {
  const controller = useHomeController()

  return (
    <HomeView
      {...controller}
      onUnlock={(a) => {
        void controller.handleUnlock(a)
      }}
    />
  )
}
