import { notFound } from 'next/navigation'
import type { Metadata } from 'next'
import { getCategoryDetail, getCategoryPriceBounds, type CategoryDetail } from '@/lib/db/queries/getCategoryDetail'
import { getProductCatalog, type ProductCatalogSort } from '@/lib/db/queries/getProductCatalog'
import { getDefaultLanguage } from '@/lib/db/queries/getlanguages'
import { getSiteInfo } from '@/lib/db/queries/getSiteInfo'
import { buildLocalizedPath } from '@/lib/i18n/buildLocalizedPath'
import JsonLd from '@/components/frontend/seo/JsonLd'
import CategoryPageClient from '@/components/frontend/category/CategoryPageClient'

const APP_URL = (process.env.NEXT_PUBLIC_APP_URL ?? 'http://localhost:3000').replace(/\/$/, '')
const PER_PAGE = 9
const SORT_VALUES: ProductCatalogSort[] = ['newest', 'price_asc', 'price_desc', 'rating', 'popular']

interface CategoryPageProps {
  params: Promise<{ locale: string; slug: string }>
  searchParams: Promise<{
    minPrice?: string
    maxPrice?: string
    rating?: string
    inStock?: string
    sort?: string
    page?: string
  }>
}

// Same idempotent decode as product/[slug]/page.tsx — the [slug] segment
// sometimes arrives still percent-encoded for non-ASCII (Urdu/Arabic)
// category slugs on this Next.js build.
function decodeSlug(slug: string): string {
  try {
    return decodeURIComponent(slug)
  } catch {
    return slug
  }
}

function buildAlternatePaths(category: CategoryDetail, defaultLocale: string): Record<string, string> {
  const paths: Record<string, string> = {}
  for (const alt of category.alternateLocales) {
    paths[alt.locale] = buildLocalizedPath(alt.locale, defaultLocale, `/category/${alt.slug}`)
  }
  return paths
}

export async function generateMetadata({ params }: CategoryPageProps): Promise<Metadata> {
  const { locale, slug } = await params
  const [category, defaultLanguage, siteInfo] = await Promise.all([
    getCategoryDetail(decodeSlug(slug), locale),
    getDefaultLanguage(),
    getSiteInfo(),
  ])
  if (!category) return {}

  const defaultLocale = defaultLanguage?.code ?? 'en'
  const alternatePaths = buildAlternatePaths(category, defaultLocale)
  const canonicalPath = buildLocalizedPath(locale, defaultLocale, `/category/${category.slug}`)

  const title = category.metaTitle || category.name
  const description =
    category.metaDescription ||
    (category.description ? category.description.replace(/<[^>]+>/g, '').slice(0, 160) : undefined)
  const ogImages = category.iconUrl ? [{ url: category.iconUrl, alt: category.altText || category.name }] : undefined

  return {
    title: `${title} | ${siteInfo.siteName}`,
    description,
    alternates: {
      canonical: `${APP_URL}${canonicalPath}`,
      languages: {
        ...Object.fromEntries(
          Object.entries(alternatePaths).map(([loc, path]) => [loc, `${APP_URL}${path}`]),
        ),
        'x-default': `${APP_URL}${alternatePaths[defaultLocale] ?? canonicalPath}`,
      },
    },
    openGraph: {
      title,
      description,
      siteName: siteInfo.siteName,
      url: `${APP_URL}${canonicalPath}`,
      images: ogImages,
      type: 'website',
    },
    twitter: {
      card: 'summary_large_image',
      title,
      description,
      images: ogImages?.map((img) => img.url),
    },
    robots: category.isIndexable ? { index: true, follow: true } : { index: false, follow: true },
  }
}

// Server Component: real category (name/description/SEO/icon) via
// getCategoryDetail.ts, real filtered/sorted/paginated products scoped to
// this one category via the already-real getProductCatalog.ts (the same
// query the /products catalog page uses, just pinned to a single category)
// — see DATA_FETCHING_PATTERN.md. CategoryPageClient only owns the
// interactive filter/sort/page navigation.
export default async function CategoryPage({ params, searchParams }: CategoryPageProps) {
  const { locale, slug } = await params
  const sp = await searchParams

  const [category, defaultLanguage] = await Promise.all([
    getCategoryDetail(decodeSlug(slug), locale),
    getDefaultLanguage(),
  ])
  if (!category) notFound()

  // Category slugs are per-language (category_translations.slug), so the
  // language switcher needs the real per-locale URL — same pattern as
  // product/[slug]/page.tsx. Without it, switching language on
  // /category/sports-shoes goes to /ur/category/sports-shoes, which doesn't
  // exist (the Urdu slug is different).
  const defaultLocale = defaultLanguage?.code ?? 'en'
  const alternatePaths = buildAlternatePaths(category, defaultLocale)

  const minPrice = sp.minPrice !== undefined ? Number(sp.minPrice) : undefined
  const maxPrice = sp.maxPrice !== undefined ? Number(sp.maxPrice) : undefined
  const minRating = sp.rating !== undefined ? Number(sp.rating) : undefined
  const inStockOnly = sp.inStock === '1'
  const sort: ProductCatalogSort = SORT_VALUES.includes(sp.sort as ProductCatalogSort) ? (sp.sort as ProductCatalogSort) : 'newest'
  const page = Math.max(1, Number(sp.page) || 1)

  const [catalog, priceBounds] = await Promise.all([
    getProductCatalog(locale, {
      categorySlugs: [category.slug],
      minPrice: Number.isFinite(minPrice) ? minPrice : undefined,
      maxPrice: Number.isFinite(maxPrice) ? maxPrice : undefined,
      minRating: Number.isFinite(minRating) ? minRating : undefined,
      inStockOnly,
      sort,
      page,
      perPage: PER_PAGE,
    }),
    getCategoryPriceBounds(category.id),
  ])

  return (
    <>
      <JsonLd data={Object.values(category.schemas) as Record<string, unknown>[]} />
      <CategoryPageClient
        category={category}
        products={catalog.products}
        total={catalog.total}
        totalPages={catalog.totalPages}
        page={page}
        priceBounds={priceBounds}
        activeMinPrice={Number.isFinite(minPrice) ? minPrice! : null}
        activeMaxPrice={Number.isFinite(maxPrice) ? maxPrice! : null}
        activeMinRating={Number.isFinite(minRating) ? minRating! : null}
        activeInStockOnly={inStockOnly}
        activeSort={sort}
        alternatePaths={alternatePaths}
        defaultLocale={defaultLocale}
      />
    </>
  )
}
