import { Link, Outlet, createFileRoute, useMatch } from '@tanstack/react-router'
import { useTranslation } from 'react-i18next'
import { useEffect, useState } from 'react'
import { ArrowRight, Calendar, Search, Tag } from 'lucide-react'
import { Input } from '@components/ui/input'
import { Badge } from '@components/ui/badge'
import { Skeleton } from '@components/ui/skeleton'
import { cn } from '@lib/utils'
import { useDebounce } from '@/hooks/use-debounce'
import { useArticleTags, useArticles } from '@/hooks/use-articles'
import { useAppSearchParams } from '@/lib/use-app-search-params'

export const Route = createFileRoute('/blog')({
  component: BlogLayout,
})

function BlogLayout() {
  const match = useMatch({ from: '/blog/$slug', shouldThrow: false })

  if (match) {
    return <Outlet />
  }

  return <BlogPage />
}

function BlogPage() {
  const { getParam, setParam } = useAppSearchParams()
  const { t } = useTranslation()
  const [page, setPage] = useState(1)

  const searchParam = getParam('search')
  const tagParam = getParam('tag')
  const [searchInput, setSearchInput] = useState(searchParam ?? '')
  const [selectedTag, setSelectedTag] = useState<string | null>(tagParam)
  const debouncedSearch = useDebounce(searchInput, 400)
  const debouncedTag = useDebounce(selectedTag ?? '', 200)

  useEffect(() => {
    const normalizedParam = searchParam ?? ''
    setSearchInput((current) =>
      current === normalizedParam ? current : normalizedParam,
    )
  }, [searchParam])

  useEffect(() => {
    const normalizedParam = searchParam ?? ''
    if (debouncedSearch === normalizedParam) {
      return
    }
    setParam('search', debouncedSearch)
    setPage(1)
  }, [debouncedSearch, searchParam, setParam])

  useEffect(() => {
    setSelectedTag(tagParam)
  }, [tagParam])

  useEffect(() => {
    const normalizedTag = tagParam ?? ''
    if (debouncedTag === normalizedTag) {
      return
    }
    if (debouncedTag) {
      setParam('tag', debouncedTag)
    } else {
      setParam('tag', '')
    }
    setPage(1)
  }, [debouncedTag, tagParam, setParam])

  const { data, isLoading } = useArticles({
    page,
    limit: 9,
    search: searchParam || undefined,
    tag: tagParam || undefined,
  })

  const { data: tags } = useArticleTags()

  const handleTagClick = (tag: string) => {
    setSelectedTag((current) => (current === tag ? null : tag))
  }

  const totalPages = data ? Math.ceil(data.total / 9) : 0

  return (
    <main className="min-h-screen px-6 pt-24 pb-16">
      <div className="mx-auto max-w-6xl">
        <div className="text-center mb-12">
          <h1 className="text-4xl font-bold tracking-tight md:text-5xl">
            {t('common.blog')}
          </h1>
          <p className="mt-4 text-lg text-muted-foreground max-w-2xl mx-auto">
            {t(
              'blog.description',
              'Thoughts, tutorials, and insights about web development and technology.',
            )}
          </p>
        </div>

        <div className="mb-8 space-y-4">
          <div className="relative max-w-md mx-auto">
            <Search className="absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" />
            <Input
              placeholder={t('blog.searchPlaceholder', 'Search articles...')}
              value={searchInput}
              onChange={(e) => setSearchInput(e.target.value)}
              className="pl-9"
            />
          </div>

          {tags && tags.length > 0 && (
            <div className="flex flex-wrap justify-center gap-2">
              {tags.map((tag) => (
                <Badge
                  key={tag}
                  variant={selectedTag === tag ? 'default' : 'outline'}
                  className="cursor-pointer transition-colors"
                  onClick={() => handleTagClick(tag)}
                >
                  <Tag className="mr-1 size-3" />
                  {tag}
                </Badge>
              ))}
              {selectedTag && (
                <Badge
                  variant="secondary"
                  className="cursor-pointer"
                  onClick={() => setSelectedTag(null)}
                >
                  {t('blog.clearFilter', 'Clear filter')}
                </Badge>
              )}
            </div>
          )}
        </div>

        {isLoading ? (
          <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
            {[1, 2, 3, 4, 5, 6].map((i) => (
              <ArticleCardSkeleton key={i} />
            ))}
          </div>
        ) : data?.articles.length === 0 ? (
          <div className="text-center py-16">
            <p className="text-muted-foreground text-lg">
              {searchParam || selectedTag
                ? t(
                    'blog.noResults',
                    'No articles found matching your criteria.',
                  )
                : t(
                    'blog.noArticles',
                    'No articles published yet. Check back soon!',
                  )}
            </p>
          </div>
        ) : (
          <>
            <div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
              {data?.articles.map((article) => (
                <ArticleCard key={article.id} article={article} />
              ))}
            </div>

            {totalPages > 1 && (
              <div className="flex justify-center items-center gap-2 mt-12">
                <button
                  onClick={() => setPage((p) => Math.max(1, p - 1))}
                  disabled={page === 1}
                  className={cn(
                    'px-4 py-2 rounded-lg border transition-colors',
                    page === 1
                      ? 'opacity-50 cursor-not-allowed'
                      : 'hover:bg-accent',
                  )}
                >
                  {t('common.previous', 'Previous')}
                </button>
                <span className="text-sm text-muted-foreground px-4">
                  {page} / {totalPages}
                </span>
                <button
                  onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
                  disabled={page === totalPages}
                  className={cn(
                    'px-4 py-2 rounded-lg border transition-colors',
                    page === totalPages
                      ? 'opacity-50 cursor-not-allowed'
                      : 'hover:bg-accent',
                  )}
                >
                  {t('common.next', 'Next')}
                </button>
              </div>
            )}
          </>
        )}
      </div>
    </main>
  )
}

interface ArticleCardProps {
  article: {
    id: string
    title: string
    slug: string
    preview: string
    coverImage?: string
    tags: Array<string>
    createdAt: string
  }
}

function ArticleCard({ article }: ArticleCardProps) {
  return (
    <Link
      to="/blog/$slug"
      params={{ slug: article.slug }}
      className="group flex flex-col rounded-xl border bg-card overflow-hidden transition-all hover:shadow-lg hover:border-primary/50"
    >
      {article.coverImage ? (
        <div className="aspect-video overflow-hidden">
          <img
            src={article.coverImage}
            alt={article.title}
            loading="lazy"
            className="w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
          />
        </div>
      ) : (
        <div className="aspect-video bg-muted flex items-center justify-center">
          <span className="text-4xl font-bold text-muted-foreground/30">
            {article.title.charAt(0)}
          </span>
        </div>
      )}

      <div className="flex flex-col flex-1 p-5">
        {article.tags.length > 0 && (
          <div className="flex flex-wrap gap-1 mb-3">
            {article.tags.slice(0, 3).map((tag) => (
              <Badge key={tag} variant="secondary" className="text-xs">
                {tag}
              </Badge>
            ))}
          </div>
        )}

        <h2 className="text-xl font-semibold mb-2 line-clamp-2 group-hover:text-primary transition-colors">
          {article.title}
        </h2>

        <p className="text-muted-foreground text-sm line-clamp-3 flex-1">
          {article.preview}
        </p>

        <div className="flex items-center justify-between mt-4 pt-4 border-t">
          <div className="flex items-center text-xs text-muted-foreground">
            <Calendar className="mr-1 size-3" />
            {new Date(article.createdAt).toLocaleDateString()}
          </div>
          <span className="text-sm font-medium text-primary flex items-center gap-1 group-hover:gap-2 transition-all">
            Read more
            <ArrowRight className="size-4" />
          </span>
        </div>
      </div>
    </Link>
  )
}

function ArticleCardSkeleton() {
  return (
    <div className="flex flex-col rounded-xl border bg-card overflow-hidden">
      <Skeleton className="aspect-video" />
      <div className="p-5 space-y-3">
        <div className="flex gap-1">
          <Skeleton className="h-5 w-16" />
          <Skeleton className="h-5 w-12" />
        </div>
        <Skeleton className="h-6 w-3/4" />
        <Skeleton className="h-4 w-full" />
        <Skeleton className="h-4 w-2/3" />
        <div className="flex justify-between pt-4 border-t">
          <Skeleton className="h-4 w-24" />
          <Skeleton className="h-4 w-20" />
        </div>
      </div>
    </div>
  )
}
