import type { Metadata } from 'next'

import { RenderShopBlocks } from '@/blocks/RenderShopBlocks'
import { RenderHero } from '@/heros/RenderHero'
import { generateMeta } from '@/utilities/generateMeta'
import configPromise from '@payload-config'
import { draftMode } from 'next/headers'
import { getPayload } from 'payload'

import type { Page, Shop } from '@/payload-types'
import type { SearchParams } from '@/utilities/shopParams'

type Props = {
  searchParams: Promise<SearchParams>
}

const hasQueryParams = (searchParams: SearchParams): boolean => Object.keys(searchParams).length > 0

const defaultShopArchiveBlock: Extract<
  NonNullable<Shop['layout']>[number],
  { blockType: 'shopArchive' }
> = {
  blockName: 'Product listing',
  blockType: 'shopArchive',
}

const resolveShopLayout = (shop: Shop | null): NonNullable<Shop['layout']> => {
  const layout = Array.isArray(shop?.layout) ? shop.layout : []
  const hasShopArchive = layout.some((block) => block?.blockType === 'shopArchive')

  if (hasShopArchive) {
    return layout
  }

  return [...layout, defaultShopArchiveBlock]
}

const hasRenderableHero = (hero: Shop['hero'] | undefined): boolean => {
  if (!hero || !hero.type || hero.type === 'none') {
    return false
  }

  return Boolean(
    hero.richText || hero.media || (Array.isArray(hero.links) && hero.links.length > 0),
  )
}

export default async function ShopPage({ searchParams }: Props) {
  const [resolvedSearchParams, shop] = await Promise.all([searchParams, queryShopGlobal()])
  const layout = resolveShopLayout(shop)

  return (
    <article className="pt-16 pb-24">
      {hasRenderableHero(shop?.hero) && <RenderHero {...(shop?.hero as Page['hero'])} />}
      <RenderShopBlocks blocks={layout} searchParams={resolvedSearchParams} />
    </article>
  )
}

export async function generateMetadata({ searchParams }: Props): Promise<Metadata> {
  const [resolvedSearchParams, shop] = await Promise.all([searchParams, queryShopGlobal()])
  const shouldIndex = !hasQueryParams(resolvedSearchParams)
  const metadata = await generateMeta({
    doc: shop,
    path: '/shop',
  })

  return {
    ...metadata,
    alternates: {
      ...(metadata.alternates || {}),
      canonical: shouldIndex ? '/shop' : null,
    },
    openGraph: {
      ...(metadata.openGraph || {}),
      url: '/shop',
    },
    robots: {
      follow: true,
      index: shouldIndex,
      googleBot: {
        follow: true,
        index: shouldIndex,
      },
    },
  }
}

const queryShopGlobal = async (): Promise<Shop | null> => {
  const { isEnabled: draft } = await draftMode()
  const payload = await getPayload({ config: configPromise })

  return payload.findGlobal({
    slug: 'shop',
    depth: 2,
    draft,
    overrideAccess: draft,
  })
}
