import { useEffect, useMemo, useState } from 'react';
import {
  ActionIcon,
  Badge,
  Button,
  Card,
  Checkbox,
  Divider,
  Drawer,
  Group,
  Modal,
  NumberInput,
  Stack,
  Text,
  TextInput,
  Title,
} from '@mantine/core';
import { IconEdit, IconPlus, IconTrash } from '@tabler/icons-react';
import { useTranslation } from 'react-i18next';
import { BilingualInput, ModalFooter, PageLoader } from '@ema-platform/ui';
import {
  useCreateStaffRoleRequirementMutation,
  useDeleteStaffRoleRequirementMutation,
  useGetStaffRoleRequirementsQuery,
  useLocalized,
  useUpdateStaffRoleRequirementMutation,
  type LicenseType,
  type StaffEvidenceRequirement,
  type StaffRoleRequirement,
} from '@ema-platform/api';
import { useRequirementActions } from '../hooks/useRequirementActions';

const ROLE_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_]*$/;

type Draft = Omit<StaffRoleRequirement, 'id' | 'licenseTypeId' | 'isActive'>;

function emptyDraft(sortOrder: number): Draft {
  return {
    roleKey: '',
    name: { en: '', am: '' },
    minCount: 1,
    maxCount: null,
    requiresExperience: false,
    minYearsExperience: null,
    requiredEvidence: [],
    sortOrder,
  };
}

/**
 * The staff a licence type demands, and the evidence each of them must
 * supply — the wizard's Staff step, which lives in its own table rather than
 * in `formSchema` and so had no editor at all: an administrator could see FF
 * asking for two ERB-certified transit employees but could not change it
 * without a re-seed.
 *
 * Rows save on confirm, like the document requirements tab — deliberately not
 * folded into the schema draft above, whose "Save schema" button replaces one
 * jsonb column in a single PUT.
 */
export function StaffRolesCard({ licenseType }: { licenseType: LicenseType }) {
  const { t } = useTranslation();
  const localized = useLocalized();
  const run = useRequirementActions();

  const { data, isLoading } = useGetStaffRoleRequirementsQuery();
  const [createRole, { isLoading: creating }] = useCreateStaffRoleRequirementMutation();
  const [updateRole, { isLoading: updating }] = useUpdateStaffRoleRequirementMutation();
  const [deleteRole] = useDeleteStaffRoleRequirementMutation();

  const [editing, setEditing] = useState<{ role: StaffRoleRequirement | null } | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<StaffRoleRequirement | null>(null);

  const roles = useMemo(
    () =>
      (data?.items ?? [])
        .filter((r) => r.licenseTypeId === licenseType.id)
        .slice()
        .sort((a, b) => a.sortOrder - b.sortOrder),
    [data, licenseType.id],
  );

  async function handleSave(draft: Draft) {
    const target = editing?.role;
    const ok = await run(
      () =>
        target
          ? updateRole({ id: target.id, ...draft }).unwrap()
          : createRole({ ...draft, licenseTypeId: licenseType.id }).unwrap(),
      target
        ? t('certReq.staff.updated', 'Staff role updated')
        : t('certReq.staff.created', 'Staff role added'),
    );
    if (ok) setEditing(null);
  }

  async function confirmDelete() {
    if (!deleteTarget) return;
    const ok = await run(
      () => deleteRole(deleteTarget.id).unwrap(),
      t('certReq.staff.deleted', 'Staff role removed'),
    );
    if (ok) setDeleteTarget(null);
  }

  return (
    <Card withBorder radius="md" p="md">
      <Group justify="space-between" align="flex-start" mb="sm">
        <div>
          <Title order={5}>{t('certReq.staff.title', 'Staff roles')}</Title>
          <Text fz="xs" c="dimmed">
            {t(
              'certReq.staff.subtitle',
              'The Staff step of this licence type: who the applicant must register and the evidence each of them uploads. Saved on confirm, separately from the sections above.',
            )}
          </Text>
        </div>
        <Button
          size="xs"
          variant="light"
          leftSection={<IconPlus size={13} />}
          onClick={() => setEditing({ role: null })}
        >
          {t('certReq.staff.add', 'Add staff role')}
        </Button>
      </Group>

      {isLoading ? (
        <PageLoader label={t('certReq.staff.loading', 'Loading staff roles…')} height={120} />
      ) : roles.length === 0 ? (
        <Text fz="sm" c="dimmed" ta="center" py="md">
          {t('certReq.staff.empty', 'No staff roles — this licence type has no Staff step.')}
        </Text>
      ) : (
        <Stack gap="xs">
          {roles.map((role) => (
            <Card key={role.id} withBorder radius="sm" p="xs" bg="var(--mantine-color-default-hover)">
              <Group justify="space-between" wrap="nowrap">
                <div style={{ minWidth: 0 }}>
                  <Group gap={6}>
                    <Text fz="sm" fw={600} truncate>{localized(role.name) || role.roleKey}</Text>
                    <Badge size="xs" variant="light">
                      {role.maxCount != null && role.maxCount === role.minCount
                        ? t('certReq.staff.exactly', 'exactly {{n}}', { n: role.minCount })
                        : t('certReq.staff.range', 'min {{min}}{{max}}', {
                            min: role.minCount,
                            max: role.maxCount != null ? ` · max ${role.maxCount}` : '',
                          })}
                    </Badge>
                    {role.requiresExperience && (
                      <Badge size="xs" color="violet" variant="light">
                        {t('certReq.staff.experience', 'experience')}
                        {role.minYearsExperience ? ` · ${role.minYearsExperience}y` : ''}
                      </Badge>
                    )}
                  </Group>
                  <Text fz="xs" c="dimmed" truncate>
                    key: {role.roleKey}
                    {role.requiredEvidence.length > 0 &&
                      ` · ${role.requiredEvidence
                        .map((e) => `${e.docKey}${e.mandatory ? '*' : ''}`)
                        .join(', ')}`}
                  </Text>
                </div>
                <Group gap={4} wrap="nowrap">
                  <ActionIcon variant="subtle" color="blue" onClick={() => setEditing({ role })}>
                    <IconEdit size={14} />
                  </ActionIcon>
                  <ActionIcon variant="subtle" color="red" onClick={() => setDeleteTarget(role)}>
                    <IconTrash size={14} />
                  </ActionIcon>
                </Group>
              </Group>
            </Card>
          ))}
        </Stack>
      )}

      <StaffRoleEditorDrawer
        opened={editing !== null}
        onClose={() => setEditing(null)}
        role={editing?.role ?? null}
        nextSortOrder={roles.length + 1}
        onSave={handleSave}
        saving={creating || updating}
      />

      <Modal
        opened={deleteTarget !== null}
        onClose={() => setDeleteTarget(null)}
        title={t('certReq.staff.delete', 'Delete staff role')}
        size="sm"
      >
        <Stack gap="md">
          <Text fz="sm">
            {t('certReq.staff.deleteConfirm', 'Remove "{{name}}" from this licence type\'s Staff step?', {
              name: deleteTarget ? localized(deleteTarget.name) || deleteTarget.roleKey : '',
            })}
          </Text>
          <ModalFooter>
            <Button variant="default" onClick={() => setDeleteTarget(null)}>
              {t('certReq.cancel', 'Cancel')}
            </Button>
            <Button color="red" onClick={confirmDelete}>{t('certReq.delete', 'Delete')}</Button>
          </ModalFooter>
        </Stack>
      </Modal>
    </Card>
  );
}

function StaffRoleEditorDrawer({
  opened,
  onClose,
  role,
  nextSortOrder,
  onSave,
  saving,
}: {
  opened: boolean;
  onClose: () => void;
  /** Null = adding a new role. */
  role: StaffRoleRequirement | null;
  nextSortOrder: number;
  onSave: (draft: Draft) => void;
  saving: boolean;
}) {
  const { t } = useTranslation();
  const [draft, setDraft] = useState<Draft>(emptyDraft(nextSortOrder));
  const [keyError, setKeyError] = useState<string | null>(null);
  const isNew = !role;

  useEffect(() => {
    if (!opened) return;
    setDraft(
      role
        ? {
            roleKey: role.roleKey,
            name: { ...role.name },
            minCount: role.minCount,
            maxCount: role.maxCount,
            requiresExperience: role.requiresExperience,
            minYearsExperience: role.minYearsExperience,
            requiredEvidence: role.requiredEvidence.map((e) => ({ ...e, label: { ...e.label } })),
            sortOrder: role.sortOrder,
          }
        : emptyDraft(nextSortOrder),
    );
    setKeyError(null);
  }, [opened, role, nextSortOrder]);

  function patchEvidence(index: number, patch: Partial<StaffEvidenceRequirement>) {
    setDraft((d) => ({
      ...d,
      requiredEvidence: d.requiredEvidence.map((e, i) => (i === index ? { ...e, ...patch } : e)),
    }));
  }

  function save() {
    const roleKey = draft.roleKey.trim();
    if (!ROLE_KEY_PATTERN.test(roleKey)) {
      setKeyError(
        t(
          'certReq.staff.keyInvalid',
          'Key must start with a letter and contain only letters, numbers, underscores',
        ),
      );
      return;
    }
    if (!draft.name.en?.trim()) return;
    // An evidence row with no docKey renders an upload slot nothing can be
    // attached to, so it is dropped rather than saved half-filled.
    onSave({
      ...draft,
      roleKey,
      requiredEvidence: draft.requiredEvidence.filter((e) => e.docKey.trim()),
    });
  }

  return (
    <Drawer
      opened={opened}
      onClose={onClose}
      position="right"
      size="md"
      title={
        <Text fw={700}>
          {isNew ? t('certReq.staff.add', 'Add staff role') : t('certReq.staff.edit', 'Edit staff role')}
        </Text>
      }
    >
      <Stack gap="md">
        <TextInput
          label={t('certReq.staff.roleKey', 'Role key')}
          placeholder="TRANSIT_CUSTOMS"
          required
          value={draft.roleKey}
          error={keyError}
          disabled={!isNew}
          description={
            isNew
              ? t('certReq.staff.roleKeyHelp', 'Letters, numbers and underscores only — identifies the role on submitted staff')
              : t('certReq.staff.roleKeyLocked', 'Key cannot change once created — staff already registered reference it')
          }
          onChange={(e) => {
            const { value } = e.currentTarget;
            setDraft((d) => ({ ...d, roleKey: value }));
          }}
        />

        <BilingualInput
          label={t('certReq.staff.name', 'Role name')}
          required
          value={{ en: draft.name.en ?? '', am: draft.name.am ?? '' }}
          onChange={(v) => setDraft((d) => ({ ...d, name: v }))}
        />

        <Group grow>
          <NumberInput
            label={t('certReq.staff.minCount', 'Minimum people')}
            min={0}
            value={draft.minCount}
            onChange={(v) => setDraft((d) => ({ ...d, minCount: typeof v === 'number' ? v : 0 }))}
            description={t('certReq.staff.minCountHelp', '0 makes the role optional')}
          />
          <NumberInput
            label={t('certReq.staff.maxCount', 'Maximum people')}
            min={0}
            value={draft.maxCount ?? ''}
            onChange={(v) => setDraft((d) => ({ ...d, maxCount: typeof v === 'number' ? v : null }))}
            description={t('certReq.staff.maxCountHelp', 'Leave empty for no limit')}
          />
        </Group>

        <Checkbox
          label={t('certReq.staff.requiresExperience', 'Requires prior experience')}
          checked={draft.requiresExperience}
          onChange={(e) => {
            const { checked } = e.currentTarget;
            setDraft((d) => ({
              ...d,
              requiresExperience: checked,
              minYearsExperience: checked ? d.minYearsExperience : null,
            }));
          }}
        />

        {draft.requiresExperience && (
          <NumberInput
            label={t('certReq.staff.minYears', 'Minimum years of experience')}
            min={0}
            value={draft.minYearsExperience ?? ''}
            onChange={(v) =>
              setDraft((d) => ({ ...d, minYearsExperience: typeof v === 'number' ? v : null }))
            }
          />
        )}

        <NumberInput
          label={t('certReq.staff.sortOrder', 'Sort order')}
          value={draft.sortOrder}
          onChange={(v) => setDraft((d) => ({ ...d, sortOrder: typeof v === 'number' ? v : 0 }))}
        />

        <Divider label={t('certReq.staff.evidence', 'Required evidence')} labelPosition="left" />
        <Text fz="xs" c="dimmed">
          {t(
            'certReq.staff.evidenceHelp',
            'One upload slot per document, asked of every person registered in this role.',
          )}
        </Text>

        {draft.requiredEvidence.map((evidence, i) => (
          <Card key={i} withBorder radius="sm" p="xs">
            <Stack gap="xs">
              <Group gap="xs" wrap="nowrap" align="flex-end">
                <TextInput
                  size="xs"
                  label={t('certReq.staff.docKey', 'Document key')}
                  placeholder="cv"
                  value={evidence.docKey}
                  onChange={(e) => patchEvidence(i, { docKey: e.currentTarget.value })}
                  style={{ flex: 1 }}
                />
                <BilingualInput
                  size="xs"
                  label={t('certReq.staff.docLabel', 'Label')}
                  value={{ en: evidence.label.en ?? '', am: evidence.label.am ?? '' }}
                  onChange={(v) => patchEvidence(i, { label: v })}
                  style={{ flex: 2 }}
                />
                <Button
                  size="xs"
                  color="red"
                  variant="subtle"
                  px={6}
                  onClick={() =>
                    setDraft((d) => ({
                      ...d,
                      requiredEvidence: d.requiredEvidence.filter((_, j) => j !== i),
                    }))
                  }
                >
                  <IconTrash size={14} />
                </Button>
              </Group>
              <Checkbox
                size="xs"
                label={t('certReq.staff.mandatory', 'Mandatory')}
                checked={evidence.mandatory}
                onChange={(e) => patchEvidence(i, { mandatory: e.currentTarget.checked })}
              />
            </Stack>
          </Card>
        ))}

        <Button
          size="xs"
          variant="light"
          leftSection={<IconPlus size={13} />}
          onClick={() =>
            setDraft((d) => ({
              ...d,
              requiredEvidence: [
                ...d.requiredEvidence,
                { docKey: '', label: { en: '', am: '' }, mandatory: true },
              ],
            }))
          }
        >
          {t('certReq.staff.addEvidence', 'Add evidence')}
        </Button>

        <ModalFooter>
          <Button variant="default" onClick={onClose}>{t('certReq.cancel', 'Cancel')}</Button>
          <Button color="teal" loading={saving} onClick={save}>
            {isNew ? t('certReq.staff.add', 'Add staff role') : t('certReq.saveChanges', 'Save changes')}
          </Button>
        </ModalFooter>
      </Stack>
    </Drawer>
  );
}
