import type { Metadata } from 'next'

import { RenderBlocks } from '@/blocks/RenderBlocks'
import { RenderHero } from '@/heros/RenderHero'
import { generateMeta } from '@/utilities/generateMeta'
import {
  getArtikelHubCategoryBySlug,
  getArtikelHubFilterCategories,
  getArtikelHubMaxPage,
  getArtikelHubPath,
  queryArtikelHubPage,
} from '@/utilities/artikelHub'
import configPromise from '@payload-config'
import { getPayload } from 'payload'
import { draftMode } from 'next/headers'
import { notFound } from 'next/navigation'
import React from 'react'

const resolveArtikelPageData = async (pageNumber: number, categorySlug?: string) => {
  const normalizedPageNumber = Number.isFinite(pageNumber) ? Math.trunc(pageNumber) : 1

  if (normalizedPageNumber < 1) {
    notFound()
  }

  const { isEnabled: draft } = await draftMode()
  const payload = await getPayload({ config: configPromise })
  const artikelPage = await queryArtikelHubPage({
    draft,
    payload,
  })

  if (!artikelPage) {
    notFound()
  }

  const activeCategory = getArtikelHubCategoryBySlug({
    page: artikelPage,
    slug: categorySlug,
  })

  if (categorySlug && !activeCategory) {
    notFound()
  }

  const maxPage = await getArtikelHubMaxPage({
    activeCategoryID: activeCategory?.id,
    draft,
    page: artikelPage,
    payload,
  })

  if (normalizedPageNumber > maxPage) {
    notFound()
  }

  return {
    maxPage,
    activeCategory,
    page: artikelPage,
    pageNumber: normalizedPageNumber,
  }
}

export const renderArtikelHubPage = async (pageNumber: number, categorySlug?: string) => {
  const { activeCategory, page, pageNumber: normalizedPageNumber } = await resolveArtikelPageData(
    pageNumber,
    categorySlug,
  )

  return (
    <article className="pt-16 pb-24">
      <RenderHero {...page.hero} />
      <RenderBlocks
        blocks={page.layout}
        postsArchiveCategorySlug={activeCategory?.slug}
        postsArchivePage={normalizedPageNumber}
      />
    </article>
  )
}

export const generateArtikelHubMetadata = async (
  pageNumber: number,
  categorySlug?: string,
): Promise<Metadata> => {
  const { activeCategory, page, pageNumber: normalizedPageNumber } = await resolveArtikelPageData(
    pageNumber,
    categorySlug,
  )
  const canonicalPath = getArtikelHubPath(normalizedPageNumber, activeCategory?.slug)
  const metadata = await generateMeta({
    doc: page,
    path: canonicalPath,
  })

  const baseTitle =
    typeof metadata.title === 'string'
      ? metadata.title
      : page.meta?.title || page.title || 'Artikel'

  const categoryTitleSuffix = activeCategory ? ` | ${activeCategory.title}` : ''
  const pageTitle =
    normalizedPageNumber > 1
      ? `${baseTitle}${categoryTitleSuffix} | Halaman ${normalizedPageNumber}`
      : `${baseTitle}${categoryTitleSuffix}`

  const description = activeCategory
    ? `${page.meta?.description || 'Pusat artikel dan panduan.'} Kategori: ${activeCategory.title}.`
    : (metadata.description ?? undefined)

  if (normalizedPageNumber <= 1) {
    return {
      ...metadata,
      alternates: {
        canonical: canonicalPath,
      },
      description,
      openGraph: {
        ...metadata.openGraph,
        description,
        title: pageTitle,
        url: canonicalPath,
      },
      title: pageTitle,
    }
  }

  return {
    ...metadata,
    alternates: {
      canonical: canonicalPath,
    },
    description,
    openGraph: {
      ...metadata.openGraph,
      description,
      title: pageTitle,
      url: canonicalPath,
    },
    title: pageTitle,
  }
}

export const generateArtikelPaginationParams = async () => {
  const payload = await getPayload({ config: configPromise })
  const artikelPage = await queryArtikelHubPage({
    draft: false,
    payload,
  })

  const maxPage = await getArtikelHubMaxPage({
    draft: false,
    page: artikelPage,
    payload,
  })

  return Array.from({ length: Math.max(0, maxPage - 1) }, (_, index) => ({
    page: String(index + 2),
  }))
}

export const generateArtikelCategoryParams = async () => {
  const payload = await getPayload({ config: configPromise })
  const artikelPage = await queryArtikelHubPage({
    draft: false,
    payload,
  })

  return getArtikelHubFilterCategories(artikelPage).map((category) => ({
    slug: category.slug,
  }))
}

export const generateArtikelCategoryPaginationParams = async () => {
  const payload = await getPayload({ config: configPromise })
  const artikelPage = await queryArtikelHubPage({
    draft: false,
    payload,
  })

  const categories = getArtikelHubFilterCategories(artikelPage)
  const params: Array<{ page: string; slug: string }> = []

  for (const category of categories) {
    const maxPage = await getArtikelHubMaxPage({
      activeCategoryID: category.id,
      draft: false,
      page: artikelPage,
      payload,
    })

    for (let pageNumber = 2; pageNumber <= maxPage; pageNumber += 1) {
      params.push({
        page: String(pageNumber),
        slug: category.slug,
      })
    }
  }

  return params
}
