import { useState, useEffect, useMemo, useCallback } from 'react'
import { useArticles } from '@/hooks/useArticles'
import { useNostrAuth } from '@/hooks/useNostrAuth'
import { applyFiltersAndSort } from '@/lib/articleFiltering'
import { getAuthorsByCategory, sortAuthors } from '@/lib/authorFiltering'
import type { Article } from '@/types/nostr'
import type { ArticleFilters } from '@/components/ArticleFilters'
import { HomeView } from '@/components/HomeView'

function usePresentationArticles(allArticles: Article[]): Map<string, 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(): {
  searchQuery: string
  setSearchQuery: React.Dispatch<React.SetStateAction<string>>
  selectedCategory: ArticleFilters['category']
  setSelectedCategory: React.Dispatch<React.SetStateAction<ArticleFilters['category']>>
  filters: ArticleFilters
  setFilters: React.Dispatch<React.SetStateAction<ArticleFilters>>
  unlockedArticles: Set<string>
  setUnlockedArticles: React.Dispatch<React.SetStateAction<Set<string>>>
} {
  const [searchQuery, setSearchQuery] = useState('')
  const [selectedCategory, setSelectedCategory] = useState<ArticleFilters['category']>(null)
  const [filters, setFilters] = useState<ArticleFilters>({
    authorPubkey: null,
    sortBy: 'newest',
    category: null,
  })
  const [unlockedArticles, setUnlockedArticles] = useState<Set<string>>(new Set())

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

function useArticlesData(searchQuery: string): {
  allArticlesRaw: Article[]
  allArticles: Article[]
  loading: boolean
  error: string | null
  loadArticleContent: (articleId: string, authorPubkey: string) => Promise<Article | null>
  presentationArticles: Map<string, Article>
} {
  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): void {
  useEffect(() => {
    setFilters((prev) => ({
      ...prev,
      category: selectedCategory,
    }))
  }, [selectedCategory, setFilters])
}

function useFilteredArticles(
  allArticlesRaw: Article[],
  searchQuery: string,
  filters: ArticleFilters,
  presentationArticles: Map<string, Article>
): 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>>>
): (article: Article) => Promise<void> {
  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(): {
  searchQuery: string
  setSearchQuery: React.Dispatch<React.SetStateAction<string>>
  selectedCategory: ArticleFilters['category']
  setSelectedCategory: React.Dispatch<React.SetStateAction<ArticleFilters['category']>>
  filters: ArticleFilters
  setFilters: React.Dispatch<React.SetStateAction<ArticleFilters>>
  articles: Article[]
  allArticles: Article[]
  authors: Article[]
  allAuthors: Article[]
  loading: boolean
  error: string | null
  unlockedArticles: Set<string>
  handleUnlock: (article: Article) => Promise<void>
} {
  const { } = useNostrAuth()
  const {
    searchQuery,
    setSearchQuery,
    selectedCategory,
    setSelectedCategory,
    filters,
    setFilters,
    unlockedArticles,
    setUnlockedArticles,
  } = useHomeState()
  const { allArticlesRaw, allArticles, loading, error, loadArticleContent, presentationArticles } =
    useArticlesData(searchQuery)

  // Presentation guard removed - users can browse without author page
  useCategorySync(selectedCategory, setFilters)
  const articles = useFilteredArticles(allArticlesRaw, searchQuery, filters, presentationArticles)
  const handleUnlock = useUnlockHandler(loadArticleContent, setUnlockedArticles)

  // Get authors by category
  const allAuthors = useMemo(() => {
    const authorsArray = Array.from(presentationArticles.values())
    return sortAuthors(authorsArray)
  }, [presentationArticles])

  const authors = useMemo(() => {
    return getAuthorsByCategory(presentationArticles, selectedCategory)
  }, [presentationArticles, selectedCategory])

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

export default function Home(): JSX.Element {
  const controller = useHomeController()

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