import {
  preventUnicodeInEmail,
  type EmailAddressFieldComponent
} from '@defra/forms-model'
import joi, { type CustomHelpers } from 'joi'

import { FormComponent } from './FormComponent.js'
import { messageTemplate } from '../pageControllers/validationOptions.js'
import {
  type ErrorMessageTemplateList,
  type FormPayload,
  type FormSubmissionError
} from '../types.js'

export class EmailAddressField extends FormComponent {
  declare options: EmailAddressFieldComponent['options']

  constructor(
    def: EmailAddressFieldComponent,
    props: ConstructorParameters<typeof FormComponent>[1]
  ) {
    super(def, props)

    const { options } = def

    let formSchema = joi
      .string()
      .trim()
      .email()
      .custom((value, helpers: CustomHelpers<string>) =>
        preventUnicodeInEmail(value, helpers)
      )
      .label(this.label)
      .required()

    if (options.required === false) {
      formSchema = formSchema.allow('')
    }

    if (options.customValidationMessage) {
      const message = options.customValidationMessage

      formSchema = formSchema.messages({
        'any.required': message,
        'string.empty': message,
        'string.email': message
      })
    } else if (options.customValidationMessages) {
      formSchema = formSchema.messages(options.customValidationMessages)
    }

    this.formSchema = formSchema.default('')
    this.stateSchema = formSchema.default(null).allow(null)
    this.options = options
  }

  getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {
    const viewModel = super.getViewModel(payload, errors)
    const { attributes } = viewModel

    attributes.autocomplete = 'email'

    return {
      ...viewModel,
      type: 'email'
    }
  }

  /**
   * For error preview page that shows all possible errors on a component
   */
  getAllPossibleErrors(): ErrorMessageTemplateList {
    return EmailAddressField.getAllPossibleErrors()
  }

  /**
   * Static version of getAllPossibleErrors that doesn't require a component instance.
   */
  static getAllPossibleErrors(): ErrorMessageTemplateList {
    return {
      baseErrors: [
        { type: 'required', template: messageTemplate.required },
        { type: 'format', template: messageTemplate.format },
        { type: 'unicode', template: messageTemplate.unicode }
      ],
      advancedSettingsErrors: []
    }
  }
}
