import {
  type FormMetadata,
  type SubmitResponsePayload
} from '@defra/forms-model'

import {
  getFormVersion,
  type checkFormStatus
} from '../../helpers.js'
import { type FormModel } from '../../models/FormModel.js'
import { type DetailItem } from '../../models/types.js'
import { categoriseData } from '../machine/v2.js'
import { FormAdapterSubmissionSchemaVersion } from '../../types/enums.js'
import {
  type FormAdapterSubmissionMessageData,
  type FormAdapterSubmissionMessageMeta,
  type FormAdapterSubmissionMessagePayload,
  type FormAdapterSubmissionMessageResult,
  type FormContext
} from '../../types.js'

export function format(
  context: FormContext,
  items: DetailItem[],
  model: FormModel,
  submitResponse: SubmitResponsePayload,
  formStatus: ReturnType<typeof checkFormStatus>,
  formMetadata?: FormMetadata
): string {
  const csvFiles = extractCsvFiles(submitResponse)

  const { main: v2Main, ...v2Data } = categoriseData(items)

  const versionMetadata = getFormVersion(model.def)

  const meta: FormAdapterSubmissionMessageMeta = {
    schemaVersion: FormAdapterSubmissionSchemaVersion.V1,
    timestamp: new Date(),
    referenceNumber: context.referenceNumber,
    formName: model.name,
    formId: formMetadata?.id ?? '',
    formSlug: formMetadata?.slug ?? '',
    status: formStatus.state,
    isPreview: formStatus.isPreview,
    notificationEmail: formMetadata?.notificationEmail ?? ''
  }

  if (versionMetadata) {
    meta.versionMetadata = versionMetadata
  }

  const main = Object.fromEntries(
    Object.entries(v2Main).map(([key, value]) => {
      if (value === undefined) {
        return [key, null]
      }

      return [key, value]
    })
  )

  const data: FormAdapterSubmissionMessageData = {
    main,
    ...v2Data
  }

  const result: FormAdapterSubmissionMessageResult = {
    files: csvFiles
  }

  const payload: FormAdapterSubmissionMessagePayload = {
    meta,
    data,
    result
  }

  return JSON.stringify(payload)
}

function extractCsvFiles(
  submitResponse: SubmitResponsePayload
): FormAdapterSubmissionMessageResult['files'] {
  const result =
    submitResponse.result as Partial<FormAdapterSubmissionMessageResult>

  return {
    main: result.files?.main ?? '',
    repeaters: result.files?.repeaters ?? {}
  }
}
