import { Loader, Select, SimpleGrid, TextInput } from '@mantine/core';
import type { FieldErrors, UseFormRegister, UseFormSetValue, UseFormWatch, UseFormTrigger } from 'react-hook-form';
import { z } from 'zod';
import type { TFunction } from 'i18next';
import { useTranslation } from 'react-i18next';
import { AmharicDatePicker } from '@ema-platform/ui';

// dob comes in as a plain yyyy-MM-dd string; skip on empty/malformed so
// dobRequired's own message takes precedence.
function isAtLeast18(dob: string): boolean {
  const birth = new Date(dob);
  if (Number.isNaN(birth.getTime())) return true;
  const today = new Date();
  const cutoff = new Date(today.getFullYear() - 18, today.getMonth(), today.getDate());
  return birth <= cutoff;
}

// Printed on the Seaman Book, so a seafarer account can't leave them blank —
// every other account type may. Blood type offers UNKNOWN, so requiring an
// answer never forces a claim. Mirrors seafarer-registration.seed-data.ts's
// `required: true` on the same fields, and the backend's own check in
// ProfileService.assertPhysicalCharacteristicsForSeafarer.
export const profileSchema = (t: TFunction, isSeafarer: boolean) =>
  z.object({
    professionId: z.string().min(1, t('profileForm.validation.professionRequired')),
    firstName: z.string().min(3, t('profileForm.validation.firstNameMin')),
    middleName: z.string().min(3, t('profileForm.validation.middleNameMin')),
    lastName: z.string().min(3, t('profileForm.validation.lastNameMin')),
    gender: z.string().min(1, t('profileForm.validation.genderRequired')),
    dob: z
      .string()
      .min(1, t('profileForm.validation.dobRequired'))
      .refine((value) => isAtLeast18(value), {
        message: t('profileForm.validation.dobMinAge'),
      }),
    pob: isSeafarer
      ? z.string().min(1, t('profileForm.validation.pobRequired'))
      : z.string().optional(),
    maritalStatus: z.string().min(1, t('profileForm.validation.maritalStatusRequired')),
    bloodType: isSeafarer
      ? z.string().min(1, t('profileForm.validation.bloodTypeRequired'))
      : z.string().optional(),
    hairColor: isSeafarer
      ? z.string().min(1, t('profileForm.validation.hairColorRequired'))
      : z.string().optional(),
    eyeColor: isSeafarer
      ? z.string().min(1, t('profileForm.validation.eyeColorRequired'))
      : z.string().optional(),
    heightCm: isSeafarer
      ? z
          .string()
          .min(1, t('profileForm.validation.heightRequired'))
          .refine((v) => Number(v) >= 100 && Number(v) <= 250, {
            message: t('profileForm.validation.heightRange'),
          })
      : z
          .string()
          .optional()
          .refine((v) => !v || (Number(v) >= 100 && Number(v) <= 250), {
            message: t('profileForm.validation.heightRange'),
          }),
  });

export type ProfileValues = z.infer<ReturnType<typeof profileSchema>>;

export const GENDERS = ['MALE', 'FEMALE'] as const;
export const MARITAL_STATUSES = ['SINGLE', 'MARRIED', 'DIVORCED', 'WIDOWED'] as const;
export const ID_TYPES = ['NID', 'VITAL', 'PASSPORT', 'DRIVERS_LICENSE'] as const;
// Must match EBloodType/EHairColor/EEyeColor on the backend (common/enums/user.enum.ts).
export const BLOOD_TYPES = [
  'A_POSITIVE', 'A_NEGATIVE', 'B_POSITIVE', 'B_NEGATIVE',
  'AB_POSITIVE', 'AB_NEGATIVE', 'O_POSITIVE', 'O_NEGATIVE', 'UNKNOWN',
] as const;
export const HAIR_COLORS = ['BLACK', 'BROWN', 'BLONDE', 'RED', 'GREY', 'WHITE', 'BALD', 'OTHER'] as const;
export const EYE_COLORS = ['BROWN', 'BLACK', 'BLUE', 'GREEN', 'HAZEL', 'GREY', 'OTHER'] as const;

interface ProfileFormContentProps {
  register: UseFormRegister<ProfileValues>;
  errors: FieldErrors<ProfileValues>;
  setValue: UseFormSetValue<ProfileValues>;
  watch: UseFormWatch<ProfileValues>;
  trigger: UseFormTrigger<ProfileValues>;
  professionsLoading: boolean;
  professionOptions: Array<{ value: string; label: string }>;
  /** Place of birth, hair/eye colour and height become required for these accounts. */
  isSeafarer: boolean;
}

export function ProfileFormContent({
  register,
  errors,
  setValue,
  watch,
  trigger,
  professionsLoading,
  professionOptions,
  isSeafarer,
}: ProfileFormContentProps) {
  const { t } = useTranslation();

  return (
    <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="md">
      <Select
        label={t('profileFields.professionId')}
        placeholder={professionsLoading ? t('common.loading') : t('common.select')}
        required
        data={professionOptions}
        error={errors.professionId?.message}
        value={watch('professionId')}
        onChange={(val) => setValue('professionId', val || '', { shouldValidate: true })}
        onBlur={() => trigger('professionId')}
        name="professionId"
        searchable
        disabled={professionsLoading}
        rightSection={professionsLoading ? <Loader size="xs" type="oval" /> : undefined}
      />
      <TextInput
        label={t('profileFields.firstName')}
        placeholder={t('profileForm.placeholders.firstName')}
        required
        {...register('firstName')}
        error={errors.firstName?.message}
      />
      <TextInput
        label={t('profileFields.middleName')}
        placeholder={t('profileForm.placeholders.middleName')}
        required
        {...register('middleName')}
        error={errors.middleName?.message}
      />
      <TextInput
        label={t('profileFields.lastName')}
        placeholder={t('profileForm.placeholders.lastName')}
        required
        {...register('lastName')}
        error={errors.lastName?.message}
      />
      <Select
        label={t('profileFields.gender')}
        placeholder={t('common.select')}
        required
        data={GENDERS.map((g) => ({ value: g, label: t(`profileForm.genders.${g}`) }))}
        error={errors.gender?.message}
        value={watch('gender')}
        onChange={(val) => setValue('gender', val || '', { shouldValidate: true })}
        onBlur={() => trigger('gender')}
        name="gender"
      />
      <AmharicDatePicker
        label={t('profileFields.dob')}
        required
        value={watch('dob')}
        onChange={(val) => setValue('dob', val, { shouldValidate: true })}
        onBlur={() => trigger('dob')}
        name="dob"
        error={errors.dob?.message}
      />
      <TextInput
        label={t('profileFields.pob')}
        placeholder={t('profileForm.placeholders.pob')}
        required={isSeafarer}
        {...register('pob')}
        error={errors.pob?.message}
      />
      <Select
        label={t('profileFields.maritalStatus')}
        placeholder={t('common.select')}
        required
        data={MARITAL_STATUSES.map((m) => ({ value: m, label: t(`profileForm.maritalStatuses.${m}`) }))}
        error={errors.maritalStatus?.message}
        value={watch('maritalStatus')}
        onChange={(val) => setValue('maritalStatus', val || '', { shouldValidate: true })}
        onBlur={() => trigger('maritalStatus')}
        name="maritalStatus"
      />
      <Select
        label={t('profileFields.bloodType')}
        placeholder={t('common.select')}
        required={isSeafarer}
        clearable={!isSeafarer}
        data={BLOOD_TYPES.map((b) => ({ value: b, label: t(`profileForm.bloodTypes.${b}`) }))}
        error={errors.bloodType?.message}
        value={watch('bloodType') || null}
        onChange={(val) => setValue('bloodType', val || '', { shouldValidate: true })}
        onBlur={() => trigger('bloodType')}
        name="bloodType"
      />
      <TextInput
        label={t('profileFields.heightCm')}
        placeholder={t('profileForm.placeholders.heightCm')}
        type="number"
        required={isSeafarer}
        {...register('heightCm')}
        error={errors.heightCm?.message}
      />
      <Select
        label={t('profileFields.hairColor')}
        placeholder={t('common.select')}
        required={isSeafarer}
        clearable={!isSeafarer}
        data={HAIR_COLORS.map((h) => ({ value: h, label: t(`profileForm.hairColors.${h}`) }))}
        error={errors.hairColor?.message}
        value={watch('hairColor') || null}
        onChange={(val) => setValue('hairColor', val || '', { shouldValidate: true })}
        onBlur={() => trigger('hairColor')}
        name="hairColor"
      />
      <Select
        label={t('profileFields.eyeColor')}
        placeholder={t('common.select')}
        required={isSeafarer}
        clearable={!isSeafarer}
        data={EYE_COLORS.map((e) => ({ value: e, label: t(`profileForm.eyeColors.${e}`) }))}
        error={errors.eyeColor?.message}
        value={watch('eyeColor') || null}
        onChange={(val) => setValue('eyeColor', val || '', { shouldValidate: true })}
        onBlur={() => trigger('eyeColor')}
        name="eyeColor"
      />
    </SimpleGrid>
  );
}
