import { useCallback, useMemo } from 'react';
import { Select, SimpleGrid, Text, TextInput } from '@mantine/core';
import type { FieldErrors, UseFormRegister, UseFormSetValue, UseFormWatch, UseFormTrigger } from 'react-hook-form';
import { z } from 'zod';
import { ethiopianPhone, optionalEthiopianPhone, CountrySelect } from '@ema-platform/ui';
import { LocationPicker } from '../../location/components/LocationPicker';
import { useGetLocationTypesQuery } from '../../location/api/location-api';
import type { Location, LocationType } from '../../location/types/location';

export const addressSchema = z.object({
  idType: z.string().min(1, 'Select ID type'),
  idNumber: z.string().trim().min(1, 'Enter ID number'),
  // Alpha-2 country code from CountrySelect; converted to a full name at submit.
  nationality: z.string().min(1, 'Select nationality'),
  primaryPhoneNumber: ethiopianPhone,
  secondaryPhoneNumber: optionalEthiopianPhone,
  email: z.string().trim().email('Invalid email').optional().or(z.literal('')),
  regionId: z.string().optional(),
  cityId: z.string().optional(),
  subCityId: z.string().optional(),
  woredaId: z.string().optional(),
  kebeleId: z.string().optional(),
  streetAddress: z.string().trim().optional(),
  postalAddress: z.string().trim().optional(),
  // Emergency contact is collected but never required — leaving it blank must
  // not stop an applicant moving on.
  emergencyContactName: z.string().trim().optional(),
  emergencyContactPhone: optionalEthiopianPhone,
  emergencyContactRelation: z.string().trim().optional(),
});

export type AddressValues = z.infer<typeof addressSchema>;

// Backend rejects anything outside this set:
// "idType must be one of the following values: NID, VITAL, PASSPORT, DRIVERS_LICENSE"
export const ID_TYPES = [
  { value: 'NID', label: 'National Id' },
  { value: 'VITAL', label: 'Vital ID' },
  { value: 'PASSPORT', label: 'Passport' },
  { value: 'DRIVERS_LICENSE', label: "Driver's License" },
] as const;

/**
 * Location types are data-driven rows (no fixed depth), so the chain is
 * mapped to a field by type *code* rather than by numeric level — this
 * resolves correctly whether or not a COUNTRY type sits above REGION.
 */
function fieldsForLocationType(type: LocationType): Array<keyof AddressValues> {
  // Location types have historically used variants such as SUBCITY,
  // SUB_CITY, and SUB-CITY. Normalize both the code and display name so a
  // selected sub-city is never dropped from the address payload.
  const typeName = `${type.code} ${type.names.en}`
    .toUpperCase()
    .replace(/[^A-Z0-9]/g, '');

  if (typeName.includes('SUBCITY')) return ['subCityId'];
  if (typeName.includes('WOREDA')) return ['woredaId'];
  if (typeName.includes('REGION')) return ['regionId'];
  if (typeName.includes('CITY')) {
    // The profile-completeness API treats the selected City as its region.
    // Keep its conventional cityId too, as other profile consumers use it.
    return ['regionId', 'cityId'];
  }
  return [];
}

interface AddressFormContentProps {
  register: UseFormRegister<AddressValues>;
  errors: FieldErrors<AddressValues>;
  setValue: UseFormSetValue<AddressValues>;
  watch: UseFormWatch<AddressValues>;
  trigger: UseFormTrigger<AddressValues>;
}

export function AddressFormContent({
  register,
  errors,
  setValue,
  watch,
  trigger,
}: AddressFormContentProps) {
  const { data: typesRes } = useGetLocationTypesQuery();
  const locationTypes = typesRes?.items;

  const typeFieldMap = useMemo(() => {
    const map = new Map<string, Array<keyof AddressValues>>();
    locationTypes?.forEach((lt) => {
      const fields = fieldsForLocationType(lt);
      if (fields.length) map.set(lt.id, fields);
    });
    return map;
  }, [locationTypes]);

  const leafId = watch('woredaId') || watch('subCityId') || watch('cityId') || watch('regionId') || undefined;

  const handleChainChange = useCallback(
    (chain: Location[]) => {
      setValue('regionId', '');
      setValue('cityId', '');
      setValue('subCityId', '');
      setValue('woredaId', '');

      chain.forEach((loc) => {
        typeFieldMap.get(loc.locationTypeId)?.forEach((field) => {
          setValue(field, loc.id);
        });
      });
    },
    [setValue, typeFieldMap],
  );

  return (
    <>
      <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="md">
        <Select
          label="ID Type"
          placeholder="Select"
          required
          data={ID_TYPES}
          error={errors.idType?.message}
          value={watch('idType')}
          onChange={(val) => setValue('idType', val || '', { shouldValidate: true })}
          onBlur={() => trigger('idType')}
          name="idType"
        />
        <TextInput
          label="ID Number"
          placeholder="Enter ID number"
          required
          {...register('idNumber')}
          error={errors.idNumber?.message}
        />
        <CountrySelect
          label="Nationality"
          demonym
          required
          value={watch('nationality') || null}
          onChange={(val) => setValue('nationality', val || '', { shouldValidate: true })}
          error={errors.nationality?.message}
        />
        <TextInput
          label="Primary Phone"
          description="From your account, edit it in the Personal tab"
          required
          readOnly
          {...register('primaryPhoneNumber')}
          error={errors.primaryPhoneNumber?.message}
        />
        <TextInput
          label="Secondary Phone"
          placeholder="+251 9XX XXX XXX"
          {...register('secondaryPhoneNumber')}
          error={errors.secondaryPhoneNumber?.message}
        />
        <TextInput
          label="Email"
          type="email"
          description="From your account, edit it in the Personal tab"
          readOnly
          {...register('email')}
          error={errors.email?.message}
        />
      </SimpleGrid>

      <Text fw={600} fz="sm" tt="uppercase" c="gray.6" mt="lg" mb="sm">
        Address
      </Text>
      {/* City / Sub-city / Woreda only — no Kebele level, kebeleId mirrors woredaId. */}
      <LocationPicker value={leafId} onChainChange={handleChainChange} maxDepth={3} />
      <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="md" mt="md">
        <TextInput
          label="Street Address"
          placeholder="Street name, house number"
          {...register('streetAddress')}
          error={errors.streetAddress?.message}
        />
        <TextInput
          label="Postal Address"
          placeholder="P.O. Box"
          {...register('postalAddress')}
          error={errors.postalAddress?.message}
        />
      </SimpleGrid>

      <Text fw={600} fz="sm" tt="uppercase" c="gray.6" mt="lg" mb="sm">
        Emergency Contact <Text span c="dimmed" fz="xs" tt="none" fw={400}>(optional)</Text>
      </Text>
      <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="md">
        <TextInput
          label="Contact Name"
          placeholder="Full name"
          {...register('emergencyContactName')}
          error={errors.emergencyContactName?.message}
        />
        <TextInput
          label="Contact Phone"
          placeholder="+251 9XX XXX XXX"
          {...register('emergencyContactPhone')}
          error={errors.emergencyContactPhone?.message}
        />
        <TextInput
          label="Relationship"
          placeholder="Spouse, Parent, etc."
          {...register('emergencyContactRelation')}
          error={errors.emergencyContactRelation?.message}
        />
      </SimpleGrid>
    </>
  );
}
