import { type SubmitPayload } from '@defra/forms-model'

import { GeospatialField } from '../../components/GeospatialField.js'
import { PaymentField } from '../../components/PaymentField.js'
import { getAnswer } from '../../components/helpers/components.js'
import {
  type DetailItem,
  type DetailItemField
} from '../../models/types.js'
import {
  formatCurrency,
  formatPaymentDate
} from '../../../payment/helper.js'

export interface SubmitRecord {
  name: string
  title: string
  value: string
}

/**
 * Builds the main submission records from field items.
 * Regular fields are converted to single records, while PaymentField
 * components are expanded into four separate records.
 */
export function buildMainRecords(items: DetailItem[]): SubmitRecord[] {
  const fieldItems = items.filter(
    (item): item is DetailItemField => 'field' in item
  )

  const records: SubmitRecord[] = []

  for (const item of fieldItems) {
    if (item.field instanceof PaymentField) {
      records.push(...buildPaymentRecords(item))
    } else if (item.field instanceof GeospatialField) {
      // Stringify of GeoJSON is done here rather than inside `getContextValueFromState`
      // so we don't incur the overhead of JSON.stringify on every request when building context
      records.push({
        name: item.name,
        title: item.label,
        value: JSON.stringify(item.field.getFormValueFromState(item.state))
      })
    } else {
      records.push({
        name: item.name,
        title: item.label,
        value: getAnswer(item.field, item.state, { format: 'data' })
      })
    }
  }

  return records
}

/**
 * Expands a PaymentField into four submission records:
 * - Payment description
 * - Payment amount (formatted with currency symbol)
 * - Payment reference
 * - Payment date (formatted date/time)
 *
 * Returns an empty array if no payment state exists.
 */
export function buildPaymentRecords(item: DetailItemField): SubmitRecord[] {
  const paymentState = (item.field as PaymentField).getPaymentStateFromState(
    item.state
  )

  if (!paymentState) {
    return []
  }

  return [
    {
      name: `${item.name}_paymentDescription`,
      title: 'Payment description',
      value: paymentState.description
    },
    {
      name: `${item.name}_paymentAmount`,
      title: 'Payment amount',
      value: formatCurrency(paymentState.amount)
    },
    {
      name: `${item.name}_paymentReference`,
      title: 'Payment reference',
      value: paymentState.reference
    },
    {
      name: `${item.name}_paymentDate`,
      title: 'Payment date',
      value: paymentState.preAuth?.createdAt
        ? formatPaymentDate(paymentState.preAuth.createdAt)
        : ''
    }
  ]
}

/**
 * Builds the repeater submission records from repeater items.
 */
export function buildRepeaterRecords(
  items: DetailItem[]
): SubmitPayload['repeaters'] {
  return items
    .filter((item) => 'subItems' in item)
    .map((item) => ({
      name: item.name,
      title: item.label,
      value: item.subItems.map((detailItems) =>
        detailItems.map((subItem) => ({
          name: subItem.name,
          title: subItem.label,
          value:
            // Stringify of GeoJSON is done here rather than inside `getContextValueFromState`
            // so we don't incur the overhead of JSON.stringify on every request when building context
            subItem.field instanceof GeospatialField
              ? JSON.stringify(
                  subItem.field.getFormValueFromState(subItem.state)
                )
              : getAnswer(subItem.field, subItem.state, { format: 'data' })
        }))
      )
    }))
}
