import { useEffect, useMemo } from 'react';
import {
  TextInput,
  Button,
  Group,
  Stack,
  Paper,
  Title,
  Text,
  Badge,
  Select,
} from '@mantine/core';
import { useForm } from '@mantine/form';
import { useTranslation } from 'react-i18next';
import { notify } from '@ema-platform/ui';
import type { Location, LocationType } from '../types/location';

interface LocationFormValues {
  code: string;
  namesEn: string;
  namesAm: string;
  locationTypeId: string;
}

interface LocationFormProps {
  locationTypes: LocationType[];
  parentLocation?: Location | null;
  editingLocation?: Location | null;
  onSubmit: (values: {
    code: string;
    names: { en: string; am: string };
    locationTypeId: string;
    parentId?: string | null;
  }) => void;
  onCancel: () => void;
  isSubmitting?: boolean;
}

export function LocationForm({
  locationTypes,
  parentLocation,
  editingLocation,
  onSubmit,
  onCancel,
  isSubmitting,
}: LocationFormProps) {
  const { t, i18n } = useTranslation();
  const locale = i18n.language as 'en' | 'am';

  const isEditing = !!editingLocation;

  const { type, allAtLevel, typesAvailable } = useMemo(() => {
    if (isEditing) {
      const lt = locationTypes.find((t) => t.id === editingLocation.locationTypeId);
      return { type: lt ?? null, allAtLevel: [lt].filter(Boolean) as LocationType[], typesAvailable: false };
    }

    if (parentLocation) {
      const parentLevel =
        locationTypes.find((lt) => lt.id === parentLocation.locationTypeId)?.level ?? 0;
      const nextLevel = locationTypes
        .filter((lt) => lt.level === parentLevel + 1)
        .sort((a, b) => a.level - b.level);
      return { type: nextLevel[0] ?? null, allAtLevel: nextLevel, typesAvailable: nextLevel.length > 1 };
    }

    const minLevel = Math.min(...locationTypes.map((lt) => lt.level));
    const roots = locationTypes
      .filter((lt) => lt.level === minLevel)
      .sort((a, b) => a.level - b.level);
    return { type: roots[0] ?? null, allAtLevel: roots, typesAvailable: roots.length > 1 };
  }, [locationTypes, parentLocation, editingLocation, isEditing]);

  const form = useForm<LocationFormValues>({
    initialValues: {
      code: '',
      namesEn: '',
      namesAm: '',
      locationTypeId: typesAvailable ? '' : (type?.id ?? ''),
    },
    validate: {
      code: (v) => (!v ? t('location.validation.codeRequired') : null),
      namesEn: (v) => (!v ? t('location.validation.nameEnRequired') : null),
      namesAm: (v) => (!v ? t('location.validation.nameAmRequired') : null),
      locationTypeId: (v) => {
        if (typesAvailable && !v) return t('location.validation.typeRequired');
        return null;
      },
    },
  });

  useEffect(() => {
    if (editingLocation) {
      form.setValues({
        code: editingLocation.code,
        namesEn: editingLocation.names.en,
        namesAm: editingLocation.names.am,
        locationTypeId: editingLocation.locationTypeId,
      });
    }
  }, [editingLocation]);

  const handleSubmit = form.onSubmit((values) => {
    const resolvedTypeId = typesAvailable ? values.locationTypeId : type?.id;
    if (!resolvedTypeId) {
      notify.error(t('location.noTypesAvailable'));
      return;
    }
    onSubmit({
      code: values.code,
      names: { en: values.namesEn, am: values.namesAm },
      locationTypeId: resolvedTypeId,
      parentId: editingLocation ? editingLocation.parentId : parentLocation?.id ?? null,
    });
  });

  const title = isEditing
    ? t('location.editTitle')
    : t('location.addTitle');

  return (
    <Paper p="lg" radius="md" withBorder>
      <Title order={5} mb="md">
        {title}
      </Title>
      {parentLocation && !isEditing && (
        <TextInput
          label={t('location.parent')}
          value={parentLocation.names[locale]}
          disabled
          mb="sm"
          size="sm"
        />
      )}
      <form onSubmit={handleSubmit}>
        <Stack gap="sm">
          {typesAvailable ? (
            <Select
              label={t('location.type')}
              placeholder={t('location.selectType')}
              data={allAtLevel.map((lt) => ({
                value: lt.id,
                // Not every locale is filled in on every row, and an option
                // with no label is unpickable — fall back to English, then the
                // code, which always exists.
                label: lt.names[locale] || lt.names.en || lt.code,
              }))}
              {...form.getInputProps('locationTypeId')}
              size="sm"
              required
              nothingFoundMessage={t('location.noTypesAvailable')}
            />
          ) : (
            <div>
              <Text size="xs" c="dimmed" fw={500} mb={4}>
                {t('location.type')}
              </Text>
              {type ? (
                <Badge size="lg" variant="light" color="blue">
                  {type.names[locale]}
                </Badge>
              ) : (
                <Text size="sm" c="red">
                  {t('location.noTypesAvailable')}
                </Text>
              )}
            </div>
          )}
          <TextInput
            label={t('location.code')}
            placeholder="e.g., ETH, AA, KK"
            {...form.getInputProps('code')}
            size="sm"
            required
          />
          <TextInput
            label={t('location.nameEn')}
            placeholder="English name"
            {...form.getInputProps('namesEn')}
            size="sm"
            required
          />
          <TextInput
            label={t('location.nameAm')}
            placeholder="የአማርኛ ስም"
            {...form.getInputProps('namesAm')}
            size="sm"
            required
          />
          <Group justify="flex-end" mt="md">
            <Button variant="default" onClick={onCancel} size="sm">
              {t('location.cancel')}
            </Button>
            <Button type="submit" loading={isSubmitting} size="sm">
              {isEditing ? t('location.update') : t('location.create')}
            </Button>
          </Group>
        </Stack>
      </form>
    </Paper>
  );
}
