'use client'

import { Suspense, useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslations } from 'next-intl'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { ChevronDown, SlidersHorizontal, X } from 'lucide-react'
import { CourseSearch } from '@/components/course-search'
import { CourseListingCard } from '@/components/course-listing-card'
import { DataStates } from '@/components/api/data-states'
import { InfiniteScrollSentinel } from '@/components/api/infinite-scroll-sentinel'
import { useFetchData } from '@/hooks/api'
import { API_QUERY } from '@/lib/api/query-presets'
import { buildUpcomingCategoryFilters } from '@/lib/api/adapters'
import type { Course, CourseCategory } from '@/lib/api/entities'
import { cn } from '@/lib/utils'

function formatCategorySlug(slug: string): string {
  return slug
    .split('-')
    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
    .join(' ')
}

function UpcomingCoursesContent() {
  const t = useTranslations('training.upcoming')
  const router = useRouter()
  const pathname = usePathname()
  const searchParams = useSearchParams()

  const categorySlug = searchParams.get('category')
  const searchParam = searchParams.get('search') ?? searchParams.get('q') ?? ''
  const yearParam = searchParams.get('year') ?? ''
  const monthParam = searchParams.get('month') ?? ''
  const venueParam = searchParams.get('venue') ?? ''

  const {
    items: categoryItems,
    isLoading: categoriesLoading,
    isError: categoriesError,
    error: categoriesFetchError,
    refetch: refetchCategories,
  } = useFetchData<CourseCategory>({
    endpoint: 'course-categories',
    params: API_QUERY.categoriesAll,
  })

  const categoriesReady = !categoriesLoading && (categoryItems?.length ?? 0) > 0

  const categories = useMemo(() => {
    const base = buildUpcomingCategoryFilters(categoryItems ?? [])

    if (!categorySlug || categoriesReady) return base

    const alreadyIncluded = base.some((item) => item.slug === categorySlug)
    if (alreadyIncluded) return base

    return [
      ...base,
      {
        name: formatCategorySlug(categorySlug),
        slug: categorySlug,
        count: 0,
      },
    ]
  }, [categoryItems, categorySlug, categoriesReady])

  const effectiveCategorySlug = useMemo(() => {
    if (!categorySlug) return null
    if (!categoriesReady) return categorySlug
    const exists = categoryItems?.some((category) => category.slug === categorySlug)
    return exists ? categorySlug : null
  }, [categorySlug, categoryItems, categoriesReady])

  const selectedCategory = useMemo(() => {
    if (!effectiveCategorySlug) return 'Upcoming Courses'
    const match = categoryItems?.find((category) => category.slug === effectiveCategorySlug)
    if (match) return match.name
    if (categorySlug) return formatCategorySlug(categorySlug)
    return 'Upcoming Courses'
  }, [categoryItems, categorySlug, effectiveCategorySlug])

  const [searchDraft, setSearchDraft] = useState(searchParam)
  const [year, setYear] = useState(yearParam)
  const [month, setMonth] = useState(monthParam)
  const [venue, setVenue] = useState(venueParam)

  useEffect(() => {
    setSearchDraft(searchParam)
  }, [searchParam])

  useEffect(() => {
    setYear(yearParam)
  }, [yearParam])

  useEffect(() => {
    setMonth(monthParam)
  }, [monthParam])

  useEffect(() => {
    setVenue(venueParam)
  }, [venueParam])

  useEffect(() => {
    if (!categoriesReady) return
    if (!categorySlug || effectiveCategorySlug) return

    const params = new URLSearchParams()
    if (searchParam.trim()) params.set('search', searchParam.trim())
    if (yearParam) params.set('year', yearParam)
    if (monthParam) params.set('month', monthParam)
    if (venueParam) params.set('venue', venueParam)
    const query = params.toString()
    router.replace(query ? `${pathname}?${query}` : pathname, { scroll: false })
  }, [
    categorySlug,
    categoriesReady,
    effectiveCategorySlug,
    searchParam,
    yearParam,
    monthParam,
    venueParam,
    pathname,
    router,
  ])

  // Upcoming list is date-based only — never driven by free-text search ranking.
  const courseParams = useMemo(() => {
    const params: Record<string, string> = {
      as_courses: 'true',
      upcoming: 'true',
      ordering: 'sort_order',
    }
    if (effectiveCategorySlug) params.category__slug = effectiveCategorySlug
    if (year) params.schedule_year = year
    if (month) params.schedule_month = month
    if (venue) params.venue = venue
    if (searchDraft.trim()) params.search = searchDraft.trim()
    return params
  }, [effectiveCategorySlug, year, month, venue, searchDraft])

  const {
    items: courses,
    isLoading,
    isError,
    isEmpty,
    error,
    refetch,
    loadMore,
    hasMore,
    isLoadingMore,
    pagination,
  } = useFetchData<Course>({
    endpoint: 'courses',
    infinite: true,
    initialPageSize: 12,
    params: courseParams,
  })

  const listedCourses = courses ?? []
  const totalCount = pagination?.count ?? listedCourses.length

  const sidebarCategories = useMemo(
    () =>
      categories.map((item) =>
        item.slug === null ? { ...item, count: totalCount || item.count } : item,
      ),
    [categories, totalCount],
  )

  const updateUrl = useCallback(
    (next: {
      category?: string | null
      q?: string
      year?: string
      month?: string
      venue?: string
    }) => {
      const params = new URLSearchParams()

      if (next.category) {
        params.set('category', next.category)
      }

      if (next.q?.trim()) {
        params.set('search', next.q.trim())
      }

      if (next.year) {
        params.set('year', next.year)
      }

      if (next.month) {
        params.set('month', next.month)
      }

      if (next.venue) {
        params.set('venue', next.venue)
      }

      const query = params.toString()
      router.replace(query ? `${pathname}?${query}` : pathname, { scroll: false })
    },
    [pathname, router],
  )

  const clearFilters = useCallback(() => {
    setSearchDraft('')
    setYear('')
    setMonth('')
    setVenue('')
    updateUrl({ category: null, q: '', year: '', month: '', venue: '' })
  }, [updateUrl])

  const handleCategoryChange = useCallback(
    (categoryName: string) => {
      const category = categories.find((item) => item.name === categoryName)
      setSearchDraft('')
      updateUrl({
        category: category?.slug ?? null,
        q: '',
        year,
        month,
        venue,
      })
    },
    [categories, year, month, venue, updateUrl],
  )

  const handleYearChange = useCallback(
    (nextYear: string) => {
      setYear(nextYear)
      updateUrl({
        category: effectiveCategorySlug,
        q: '',
        year: nextYear,
        month,
        venue,
      })
    },
    [effectiveCategorySlug, month, venue, updateUrl],
  )

  const handleMonthChange = useCallback(
    (nextMonth: string) => {
      setMonth(nextMonth)
      updateUrl({
        category: effectiveCategorySlug,
        q: '',
        year,
        month: nextMonth,
        venue,
      })
    },
    [effectiveCategorySlug, year, venue, updateUrl],
  )

  const handleVenueChange = useCallback(
    (nextVenue: string) => {
      setVenue(nextVenue)
      updateUrl({
        category: effectiveCategorySlug,
        q: '',
        year,
        month,
        venue: nextVenue,
      })
    },
    [effectiveCategorySlug, year, month, updateUrl],
  )

  const [leadCourse, ...restCourses] = listedCourses
  const hasActiveFilters =
    selectedCategory !== 'Upcoming Courses' || Boolean(year) || Boolean(month) || Boolean(venue)

  return (
    <main>
      <section className="relative overflow-hidden bg-[oklch(0.22_0.07_343)] text-white">
        <div
          className="pointer-events-none absolute inset-0"
          style={{
            backgroundImage:
              'radial-gradient(ellipse 55% 50% at 90% 10%, oklch(0.50 0.09 179 / 0.35), transparent), radial-gradient(ellipse 40% 40% at 8% 90%, oklch(0.75 0.15 81 / 0.14), transparent)',
          }}
          aria-hidden
        />
        <div className="container-wide relative py-14 sm:py-16 md:py-20">
          <div className="grid gap-10 lg:grid-cols-[0.95fr_1.05fr] lg:items-end lg:gap-14">
            <div>
              <p className="text-[11px] font-bold uppercase tracking-[0.22em] text-accent">{t('hero.eyebrow')}</p>
              <span className="mt-3 block h-0.5 w-10 bg-accent" aria-hidden />
              <h1 className="mt-5 font-heading text-4xl leading-snug sm:text-5xl md:text-[3.25rem]">
                {t('hero.title')}
              </h1>
              <p className="mt-4 max-w-xl text-base leading-7 text-white/72 sm:text-lg sm:leading-8">
                {t('hero.description')}
              </p>
              <dl className="mt-8 grid grid-cols-3 gap-4 border-t border-white/15 pt-6">
                <div>
                  <dt className="text-[10px] font-bold uppercase tracking-[0.14em] text-white/45">
                    Programmes
                  </dt>
                  <dd className="mt-1 font-heading text-2xl text-white sm:text-3xl">
                    {isLoading ? '—' : totalCount}
                  </dd>
                </div>
                <div>
                  <dt className="text-[10px] font-bold uppercase tracking-[0.14em] text-white/45">
                    Showing
                  </dt>
                  <dd className="mt-1 font-heading text-2xl text-white sm:text-3xl">
                    {isLoading ? '—' : listedCourses.length}
                  </dd>
                </div>
                <div>
                  <dt className="text-[10px] font-bold uppercase tracking-[0.14em] text-white/45">
                    Format
                  </dt>
                  <dd className="mt-1 font-heading text-2xl text-white sm:text-3xl">Live</dd>
                </div>
              </dl>
            </div>

            <div className="relative z-40">
              <CourseSearch
                variant="prominent"
                placeholder="Search by course name…"
                value={searchDraft}
                onQueryChange={setSearchDraft}
                year={year}
                onYearChange={handleYearChange}
                month={month}
                onMonthChange={handleMonthChange}
                venue={venue}
                onVenueChange={handleVenueChange}
                showPrice={false}
              />
            </div>
          </div>
        </div>
        <div className="h-px bg-gradient-to-r from-transparent via-accent/70 to-transparent" />
      </section>

      <section className="sticky top-[4.25rem] z-30 border-b border-border/70 bg-white/95 backdrop-blur-md">
        <div className="container-wide py-4">
          <div className="mb-3 flex items-center justify-between gap-3">
            <div>
              <p className="text-[11px] font-bold uppercase tracking-[0.18em] text-secondary">
                Categories
              </p>
              <p className="mt-0.5 text-sm text-muted-foreground">
                {selectedCategory !== 'Upcoming Courses' ? selectedCategory : 'All upcoming programmes'}
                {' · '}
                <span className="font-semibold text-foreground">{totalCount}</span> results
              </p>
            </div>
            {hasActiveFilters ? (
              <button
                type="button"
                onClick={clearFilters}
                className="inline-flex h-9 items-center gap-1.5 border border-border px-3 text-xs font-semibold text-primary transition hover:border-primary"
              >
                <X className="h-3.5 w-3.5" />
                Clear filters
              </button>
            ) : null}
          </div>

          <div className="lg:hidden">
            <label className="relative block">
              <span className="sr-only">Filter by category</span>
              <SlidersHorizontal className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
              <select
                value={selectedCategory}
                onChange={(event) => handleCategoryChange(event.target.value)}
                disabled={categoriesLoading}
                className="h-11 w-full appearance-none border border-border bg-[oklch(0.985_0.008_343)] pl-10 pr-10 text-sm font-medium text-foreground focus:outline-none focus:ring-2 focus:ring-primary/30 disabled:cursor-wait disabled:opacity-60"
              >
                {categoriesLoading ? (
                  <option value="Upcoming Courses">Loading categories…</option>
                ) : categoriesError ? (
                  <option value="Upcoming Courses">Categories unavailable</option>
                ) : (
                  sidebarCategories.map((category) => (
                    <option key={category.name} value={category.name}>
                      {category.name} ({category.count})
                    </option>
                  ))
                )}
              </select>
              <ChevronDown className="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
            </label>
            {categoriesError ? (
              <button
                type="button"
                onClick={() => refetchCategories()}
                className="mt-2 text-sm font-semibold text-primary"
              >
                Retry loading categories
              </button>
            ) : null}
          </div>

          <div className="hidden lg:block">
            {categoriesLoading ? (
              <div className="flex gap-2" aria-busy="true">
                {Array.from({ length: 8 }).map((_, index) => (
                  <div key={index} className="h-10 w-28 animate-pulse bg-muted" />
                ))}
              </div>
            ) : categoriesError ? (
              <div className="flex items-center gap-3 border border-destructive/30 bg-destructive/5 px-4 py-3">
                <p className="text-sm text-destructive">
                  {categoriesFetchError?.message ?? 'Could not load categories'}
                </p>
                <button
                  type="button"
                  onClick={() => refetchCategories()}
                  className="text-sm font-semibold text-primary"
                >
                  Retry
                </button>
              </div>
            ) : (
              <nav
                aria-label="Course categories"
                className="flex gap-2 overflow-x-auto pb-1 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
              >
                {sidebarCategories.map((category) => {
                  const active = selectedCategory === category.name
                  return (
                    <button
                      key={category.name}
                      type="button"
                      onClick={() => handleCategoryChange(category.name)}
                      className={cn(
                        'inline-flex h-10 shrink-0 items-center gap-2 border px-4 text-sm font-semibold transition',
                        active
                          ? 'border-primary bg-primary text-primary-foreground'
                          : 'border-border bg-[oklch(0.985_0.008_343)] text-foreground hover:border-secondary hover:bg-white',
                      )}
                      aria-current={active ? 'true' : undefined}
                    >
                      <span className="max-w-[14rem] truncate">{category.name}</span>
                      <span
                        className={cn(
                          'tabular-nums text-xs',
                          active ? 'text-primary-foreground/80' : 'text-muted-foreground',
                        )}
                      >
                        {category.count}
                      </span>
                    </button>
                  )
                })}
              </nav>
            )}
          </div>
        </div>
      </section>

      <section className="border-b border-border/70 bg-[oklch(0.975_0.01_343)] py-10 sm:py-12 md:py-16">
        <div className="container-wide">
          <div className="mb-8 flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
            <div>
              <p className="text-[11px] font-bold uppercase tracking-[0.18em] text-secondary">
                Catalogue
              </p>
              <h2 className="mt-2 font-heading text-2xl text-foreground sm:text-3xl">
                {selectedCategory === 'Upcoming Courses'
                  ? 'All upcoming programmes'
                  : selectedCategory}
              </h2>
              <p className="mt-2 max-w-2xl text-sm leading-6 text-muted-foreground">
                Showing{' '}
                <span className="font-semibold text-foreground">{listedCourses.length}</span> of{' '}
                <span className="font-semibold text-foreground">{totalCount}</span> upcoming
                programmes. Each course card links to its complete schedule.
              </p>
            </div>
          </div>

          <DataStates
            isLoading={isLoading}
            isError={isError}
            isEmpty={isEmpty}
            error={error}
            loadingMessage="Loading upcoming courses…"
            emptyMessage={t("empty")}
            onRetry={refetch}
            skeleton={
              <div className="grid gap-4 md:grid-cols-2" aria-busy="true">
                <div className="min-h-[280px] animate-pulse bg-muted md:col-span-2 md:min-h-[320px]" />
                {Array.from({ length: 4 }).map((_, i) => (
                  <div key={i} className="min-h-[320px] animate-pulse bg-muted" />
                ))}
              </div>
            }
          >
            <div className="grid gap-4 md:grid-cols-2">
              {leadCourse ? (
                <CourseListingCard key={leadCourse.id} course={leadCourse} variant="featured" />
              ) : null}
              {restCourses.map((course) => (
                <CourseListingCard key={course.id} course={course} />
              ))}
            </div>

            <InfiniteScrollSentinel
              hasMore={hasMore}
              isLoadingMore={isLoadingMore}
              onLoadMore={loadMore}
            />
          </DataStates>
        </div>
      </section>
    </main>
  )
}

function UpcomingCoursesFallback() {
  const t = useTranslations('training.upcoming')
  return (
    <main>
      <section className="bg-[oklch(0.22_0.07_343)] py-20 text-white">
        <div className="container-wide">
          <p className="text-[11px] font-bold uppercase tracking-[0.22em] text-accent">{t('hero.eyebrow')}</p>
          <h1 className="mt-4 font-heading text-4xl sm:text-5xl">{t('hero.title')}</h1>
          <p className="mt-4 text-white/70">{t('hero.description')}</p>
        </div>
      </section>
      <div className="container-wide py-20 text-center text-muted-foreground">{t('loading')}</div>
    </main>
  )
}

export default function UpcomingCoursesPage() {
  return (
    <Suspense fallback={<UpcomingCoursesFallback />}>
      <UpcomingCoursesContent />
    </Suspense>
  )
}
