import { useEffect, useState } from 'react';
import {
  ActionIcon,
  Alert,
  Badge,
  Button,
  Card,
  Group,
  Modal,
  Stack,
  Text,
} from '@mantine/core';
import {
  IconAlertTriangle,
  IconChevronDown,
  IconChevronUp,
  IconEdit,
  IconGripVertical,
  IconPlus,
  IconTrash,
} from '@tabler/icons-react';
import { useTranslation } from 'react-i18next';
import { EmptyState, ModalFooter, notify } from '@ema-platform/ui';
import {
  extractErrorMessage,
  useGetFormSchemaPaletteQuery,
  useLocalized,
  useUpdateFormSchemaMutation,
  useValidateFormSchemaMutation,
  type FormFieldConfig,
  type FormSectionConfig,
  type LicenseType,
  type SchemaIssue,
} from '@ema-platform/api';
import { collectConditionTargets } from '../config/schema-paths';
import { useRequirementActions } from '../hooks/useRequirementActions';
import { FieldEditorDrawer } from './FieldEditorDrawer';
import { SectionEditorDrawer } from './SectionEditorDrawer';
import { StaffRolesCard } from './StaffRolesCard';

function moveItem<T>(list: T[], index: number, direction: -1 | 1): T[] {
  const target = index + direction;
  if (target < 0 || target >= list.length) return list;
  const next = [...list];
  [next[index], next[target]] = [next[target], next[index]];
  return next.map((item, i) => ({ ...item, sortOrder: i } as T));
}

/**
 * Sections/fields editor for one licence type's `formSchema`.
 *
 * Edits build up a local draft; nothing is sent until "Save schema" — the
 * server replaces the whole `formSchema` in one `PUT`, so partial saves would
 * not match what the API accepts anyway. "Check for errors" dry-runs the same
 * lint the save uses, so an author can fix problems before committing.
 */
export function FormSchemaTab({ licenseType }: { licenseType: LicenseType }) {
  const { t } = useTranslation();
  const localized = useLocalized();
  const run = useRequirementActions();

  const { data: palette } = useGetFormSchemaPaletteQuery();
  const [saveSchema, { isLoading: saving }] = useUpdateFormSchemaMutation();
  const [validateSchema, { isLoading: validating }] = useValidateFormSchemaMutation();

  const [sections, setSections] = useState<FormSectionConfig[]>(licenseType.formSchema.sections);
  const [issues, setIssues] = useState<SchemaIssue[] | null>(null);
  const [dirty, setDirty] = useState(false);

  // A newly selected licence type replaces the draft outright. Deliberately
  // keyed on the id alone: a background refetch of the *same* type (e.g. the
  // list tag invalidation right after this tab's own save) must not clobber
  // whatever the admin is mid-editing.
  useEffect(() => {
    setSections(licenseType.formSchema.sections);
    setIssues(null);
    setDirty(false);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [licenseType.id]);

  const [sectionDrawer, setSectionDrawer] = useState<{ section: FormSectionConfig | null } | null>(null);
  const [fieldDrawer, setFieldDrawer] = useState<{ sectionKey: string; field: FormFieldConfig | null } | null>(null);
  const [deleteSection, setDeleteSection] = useState<FormSectionConfig | null>(null);
  const [deleteField, setDeleteField] = useState<{ sectionKey: string; field: FormFieldConfig } | null>(null);

  const conditionTargets = collectConditionTargets(sections);

  function mutate(next: FormSectionConfig[]) {
    setSections(next);
    setDirty(true);
    setIssues(null);
  }

  function saveSection(meta: Omit<FormSectionConfig, 'fields'>) {
    const editing = sectionDrawer?.section;
    if (editing) {
      mutate(sections.map((s) => (s.key === editing.key ? { ...s, ...meta } : s)));
    } else {
      mutate([...sections, { ...meta, fields: [] }]);
    }
    setSectionDrawer(null);
  }

  function saveField(field: FormFieldConfig) {
    if (!fieldDrawer) return;
    mutate(
      sections.map((s) => {
        if (s.key !== fieldDrawer.sectionKey) return s;
        const exists = fieldDrawer.field;
        return {
          ...s,
          fields: exists
            ? s.fields.map((f) => (f.key === exists.key ? field : f))
            : [...s.fields, field],
        };
      }),
    );
    setFieldDrawer(null);
  }

  function confirmDeleteSection() {
    if (!deleteSection) return;
    mutate(sections.filter((s) => s.key !== deleteSection.key));
    setDeleteSection(null);
  }

  function confirmDeleteField() {
    if (!deleteField) return;
    mutate(
      sections.map((s) =>
        s.key === deleteField.sectionKey
          ? { ...s, fields: s.fields.filter((f) => f.key !== deleteField.field.key) }
          : s,
      ),
    );
    setDeleteField(null);
  }

  async function checkForErrors() {
    try {
      const result = await validateSchema({
        formSchema: { sections },
        licenseTypeId: licenseType.id,
      }).unwrap();
      setIssues(result.issues);
      if (result.valid) notify.success(t('certReq.schema.noIssues', 'No issues found'));
    } catch (err) {
      notify.error(extractErrorMessage(err));
    }
  }

  async function handleSave() {
    const ok = await run(
      () => saveSchema({ id: licenseType.id, formSchema: { sections } }).unwrap(),
      t('certReq.schema.saved', 'Form schema saved'),
    );
    if (ok) {
      setDirty(false);
      setIssues(null);
    }
  }

  return (
    <Stack gap="md">
      <Group justify="space-between">
        <Text fz="sm" c="dimmed">
          {t(
            'certReq.schema.subtitle',
            'Sections and fields the applicant sees for this licence type. Sections sharing a group render together on one wizard step.',
          )}
        </Text>
        <Group gap="sm">
          <Button variant="default" loading={validating} onClick={checkForErrors}>
            {t('certReq.schema.checkErrors', 'Check for errors')}
          </Button>
          <Button
            leftSection={<IconPlus size={15} />}
            variant="default"
            onClick={() => setSectionDrawer({ section: null })}
          >
            {t('certReq.section.add', 'Add section')}
          </Button>
          <Button color="teal" loading={saving} disabled={!dirty} onClick={handleSave}>
            {t('certReq.schema.save', 'Save schema')}
          </Button>
        </Group>
      </Group>

      {issues !== null && issues.length > 0 && (
        <Alert color="red" icon={<IconAlertTriangle size={16} />} title={t('certReq.schema.issuesFound', 'Issues found')}>
          <Stack gap={4}>
            {issues.map((issue, i) => (
              <Text key={i} fz="xs">
                <Text span fw={600}>{issue.path}</Text>: {issue.message}
              </Text>
            ))}
          </Stack>
        </Alert>
      )}

      {sections.length === 0 ? (
        <EmptyState
          title={t('certReq.schema.empty', 'No sections yet')}
          description={t('certReq.schema.emptyBody', 'Add a section to start building this licence type\'s form.')}
          action={{ label: t('certReq.section.add', 'Add section'), onClick: () => setSectionDrawer({ section: null }) }}
        />
      ) : (
        <Stack gap="md">
          {sections.map((section, sIndex) => (
            <Card key={section.key} withBorder radius="md" p="md">
              <Group justify="space-between" align="flex-start" mb="sm">
                <Group gap="xs" wrap="nowrap">
                  <IconGripVertical size={16} color="var(--mantine-color-dimmed)" />
                  <div>
                    <Group gap="xs">
                      <Text fw={700}>{localized(section.title) || section.key}</Text>
                      {section.group && <Badge size="xs" variant="light">{t('certReq.section.groupBadge', 'group')}: {section.group}</Badge>}
                      {section.showWhen && <Badge size="xs" color="violet" variant="light">{t('certReq.condition.badge', 'conditional')}</Badge>}
                    </Group>
                    <Text fz="xs" c="dimmed">key: {section.key}</Text>
                  </div>
                </Group>
                <Group gap={4}>
                  <ActionIcon variant="subtle" disabled={sIndex === 0} onClick={() => mutate(moveItem(sections, sIndex, -1))}>
                    <IconChevronUp size={14} />
                  </ActionIcon>
                  <ActionIcon variant="subtle" disabled={sIndex === sections.length - 1} onClick={() => mutate(moveItem(sections, sIndex, 1))}>
                    <IconChevronDown size={14} />
                  </ActionIcon>
                  <ActionIcon variant="subtle" color="blue" onClick={() => setSectionDrawer({ section })}>
                    <IconEdit size={14} />
                  </ActionIcon>
                  <ActionIcon variant="subtle" color="red" onClick={() => setDeleteSection(section)}>
                    <IconTrash size={14} />
                  </ActionIcon>
                </Group>
              </Group>

              <Stack gap="xs">
                {section.fields.map((field, fIndex) => (
                  <Card key={field.key} withBorder radius="sm" p="xs" bg="var(--mantine-color-default-hover)">
                    <Group justify="space-between" wrap="nowrap">
                      <Group gap="xs" wrap="nowrap" style={{ minWidth: 0 }}>
                        <div style={{ minWidth: 0 }}>
                          <Group gap={6} wrap="nowrap">
                            <Text fz="sm" fw={600} truncate>{localized(field.label) || field.key}</Text>
                            {field.required && <Text fz="xs" c="red" fw={700}>*</Text>}
                          </Group>
                          <Group gap={6}>
                            <Badge size="xs" variant="light">{field.type}</Badge>
                            <Text fz="xs" c="dimmed" truncate>key: {field.key}</Text>
                            {field.showWhen && <Badge size="xs" color="violet" variant="light">{t('certReq.condition.badge', 'conditional')}</Badge>}
                          </Group>
                        </div>
                      </Group>
                      <Group gap={4} wrap="nowrap">
                        <ActionIcon variant="subtle" size="sm" disabled={fIndex === 0} onClick={() => mutate(sections.map((s) => (s.key === section.key ? { ...s, fields: moveItem(s.fields, fIndex, -1) } : s)))}>
                          <IconChevronUp size={13} />
                        </ActionIcon>
                        <ActionIcon variant="subtle" size="sm" disabled={fIndex === section.fields.length - 1} onClick={() => mutate(sections.map((s) => (s.key === section.key ? { ...s, fields: moveItem(s.fields, fIndex, 1) } : s)))}>
                          <IconChevronDown size={13} />
                        </ActionIcon>
                        <ActionIcon variant="subtle" size="sm" color="blue" onClick={() => setFieldDrawer({ sectionKey: section.key, field })}>
                          <IconEdit size={13} />
                        </ActionIcon>
                        <ActionIcon variant="subtle" size="sm" color="red" onClick={() => setDeleteField({ sectionKey: section.key, field })}>
                          <IconTrash size={13} />
                        </ActionIcon>
                      </Group>
                    </Group>
                  </Card>
                ))}

                <Button
                  size="xs"
                  variant="subtle"
                  leftSection={<IconPlus size={13} />}
                  onClick={() => setFieldDrawer({ sectionKey: section.key, field: null })}
                >
                  {t('certReq.field.add', 'Add field')}
                </Button>
              </Stack>
            </Card>
          ))}
        </Stack>
      )}

      <StaffRolesCard licenseType={licenseType} />

      <SectionEditorDrawer
        opened={sectionDrawer !== null}
        onClose={() => setSectionDrawer(null)}
        section={sectionDrawer?.section ?? null}
        onSave={saveSection}
        palette={palette}
        conditionTargets={conditionTargets}
      />

      <FieldEditorDrawer
        opened={fieldDrawer !== null}
        onClose={() => setFieldDrawer(null)}
        field={fieldDrawer?.field ?? null}
        onSave={saveField}
        palette={palette}
        conditionTargets={conditionTargets}
      />

      <Modal opened={deleteSection !== null} onClose={() => setDeleteSection(null)} title={t('certReq.section.delete', 'Delete section')} size="sm">
        <Stack gap="md">
          <Text fz="sm">
            {t('certReq.section.deleteConfirm', 'Remove "{{name}}" and all of its fields from this schema?', {
              name: deleteSection ? localized(deleteSection.title) || deleteSection.key : '',
            })}
          </Text>
          <ModalFooter>
            <Button variant="default" onClick={() => setDeleteSection(null)}>{t('certReq.cancel', 'Cancel')}</Button>
            <Button color="red" onClick={confirmDeleteSection}>{t('certReq.delete', 'Delete')}</Button>
          </ModalFooter>
        </Stack>
      </Modal>

      <Modal opened={deleteField !== null} onClose={() => setDeleteField(null)} title={t('certReq.field.delete', 'Delete field')} size="sm">
        <Stack gap="md">
          <Text fz="sm">
            {t('certReq.field.deleteConfirm', 'Remove "{{name}}" from this section?', {
              name: deleteField ? localized(deleteField.field.label) || deleteField.field.key : '',
            })}
          </Text>
          <ModalFooter>
            <Button variant="default" onClick={() => setDeleteField(null)}>{t('certReq.cancel', 'Cancel')}</Button>
            <Button color="red" onClick={confirmDeleteField}>{t('certReq.delete', 'Delete')}</Button>
          </ModalFooter>
        </Stack>
      </Modal>
    </Stack>
  );
}
