import 'server-only'

import configPromise from '@payload-config'
import type { FormFieldBlock } from '@payloadcms/plugin-form-builder/types'
import { getPayload } from 'payload'

import type { Form as FormType, ContactFormBlock as ContactFormBlockProps } from '@/payload-types'

import { ContactFormBlockClient } from './Client'

type RenderableForm = {
  id: FormType['id']
  confirmationMessage: FormType['confirmationMessage']
  confirmationType: FormType['confirmationType']
  fields: FormFieldBlock[]
  redirect: FormType['redirect']
  submitButtonLabel: FormType['submitButtonLabel']
}

const normalizeField = (field: NonNullable<FormType['fields']>[number]): FormFieldBlock => {
  const normalizedField = { ...field }

  if (normalizedField.blockName == null) {
    delete normalizedField.blockName
  }

  if (normalizedField.blockType === 'select' && Array.isArray(normalizedField.options)) {
    normalizedField.options = normalizedField.options.map(({ id: _id, ...option }) => option)
  }

  return normalizedField as FormFieldBlock
}

const toRenderableForm = (form: Partial<FormType> | null | undefined): null | RenderableForm => {
  if (!form?.id || !Array.isArray(form.fields)) {
    return null
  }

  return {
    id: form.id,
    confirmationMessage: form.confirmationMessage,
    confirmationType: form.confirmationType,
    fields: form.fields.map((field) => normalizeField(field)),
    redirect: form.redirect,
    submitButtonLabel: form.submitButtonLabel,
  }
}

const resolveForm = async (
  form: ContactFormBlockProps['form'],
): Promise<null | RenderableForm> => {
  if (form && typeof form === 'object') {
    return toRenderableForm(form)
  }

  if (!form) {
    return null
  }

  const payload = await getPayload({ config: configPromise })
  const resolved = await payload.findByID({
    collection: 'forms',
    id: form,
    depth: 2,
    overrideAccess: true,
    select: {
      confirmationMessage: true,
      confirmationType: true,
      fields: true,
      redirect: true,
      submitButtonLabel: true,
    },
  })

  return toRenderableForm(resolved)
}

export const ContactFormBlock = async (
  props: ContactFormBlockProps & {
    id?: number | string
  },
) => {
  const renderableForm = await resolveForm(props.form)

  return (
    <ContactFormBlockClient
      blockName={props.blockName}
      blockType={props.blockType}
      enableIntro={props.enableIntro}
      footerNote={props.footerNote}
      form={renderableForm}
      introContent={props.introContent}
    />
  )
}
