import { useEffect, useMemo, useState } from 'react';
import {
  Alert,
  Badge,
  Button,
  Checkbox,
  Group,
  Loader,
  Modal,
  Stack,
  Text,
  Title,
} from '@mantine/core';
import { IconAlertTriangle, IconBuildingWarehouse } from '@tabler/icons-react';
import {
  extractErrorMessage,
  localized,
  useGetLicenseTypesQuery,
  useGetMyOperatorTypesQuery,
  useUpdateMyOperatorTypesMutation,
} from '@ema-platform/api';
import { notify, ModalFooter } from '@ema-platform/ui';
import { useDateDisplayer } from '@ema-platform/shared';

/**
 * The applicant's modes of operation — what they do, and therefore which
 * licences the portal offers them.
 *
 * The options come from the licence-type catalogue rather than a list in the
 * code, so a sixth licence type configured by EMA appears here without a
 * release. Removing a mode is confirmed separately from adding one: adding
 * only widens what is on offer, while removing changes what the applicant can
 * still file.
 */
export function OperationsFormContent({
  onSaved,
}: {
  /** Where to go once the set is stored — used by the onboarding step. */
  onSaved?: () => void;
} = {}) {
  const { data: catalogue, isLoading: loadingTypes } = useGetLicenseTypesQuery();
  const { data: mine, isLoading: loadingMine } = useGetMyOperatorTypesQuery();
  const [save, { isLoading: saving }] = useUpdateMyOperatorTypesMutation();

  const declaredIds = useMemo(
    () => (mine?.items ?? []).map((o) => o.licenseTypeId),
    [mine],
  );
  const [selected, setSelected] = useState<string[]>([]);
  const [confirmingRemoval, setConfirmingRemoval] = useState(false);

  // Re-sync whenever the server's answer changes — including after a save, so
  // the form reflects what was actually stored rather than what was typed.
  useEffect(() => setSelected(declaredIds), [declaredIds]);

  const options = useMemo(
    () =>
      (catalogue?.items ?? [])
        .filter((t) => t.isActive)
        // A mode of operation is an operator licence; person-centric
        // registrations (seafarer) cannot be declared as one.
        .filter((t) => t.requiresOperatorMode !== false),
    [catalogue],
  );

  const showDate = useDateDisplayer();
  const removed = declaredIds.filter((id) => !selected.includes(id));
  const dirty =
    removed.length > 0 || selected.some((id) => !declaredIds.includes(id));

  const lastChanged = useMemo(() => {
    const dates = (mine?.items ?? [])
      .map((o) => o.declaredAt)
      .filter((d): d is string => Boolean(d))
      .sort();
    return dates.length > 0 ? dates[dates.length - 1] : null;
  }, [mine]);

  async function persist() {
    try {
      await save({ licenseTypeIds: selected }).unwrap();
      setConfirmingRemoval(false);
      notify.success(
        'The licences you can apply for have been updated to match.',
        'Operations updated',
      );
      onSaved?.();
    } catch (err) {
      notify.error(extractErrorMessage(err), 'Could not save');
    }
  }

  if (loadingTypes || loadingMine) {
    return <Loader size="sm" />;
  }

  const removedNames = options
    .filter((t) => removed.includes(t.id))
    .map((t) => localized(t.name));

  return (
    <Stack gap="xl">
      <div>
        <Title order={5}>Mode of operation</Title>
        <Text size="sm" c="dimmed" mb="md">
          What your company operates as. This decides which licences you are
          offered — you can change it whenever your business changes.
        </Text>

        <Checkbox.Group value={selected} onChange={setSelected}>
          <Stack gap="sm">
            {options.map((type) => (
              <Checkbox
                key={type.id}
                value={type.id}
                label={
                  <Group gap="xs" wrap="nowrap">
                    <Text size="sm">{localized(type.name)}</Text>
                    {declaredIds.includes(type.id) && (
                      <Badge size="xs" variant="light" color="teal">
                        Current
                      </Badge>
                    )}
                  </Group>
                }
                description={
                  type.description ? localized(type.description) : undefined
                }
              />
            ))}
          </Stack>
        </Checkbox.Group>

        {options.length === 0 && (
          <Text size="sm" c="dimmed">
            No licence types are configured yet. Contact EMA if you were
            expecting one.
          </Text>
        )}
      </div>

      {selected.length === 0 && (
        <Alert
          variant="light"
          color="orange"
          icon={<IconAlertTriangle size={18} />}
          title="No operations selected"
        >
          With none selected you will not be offered any licence to apply for.
          Existing applications and issued licences are unaffected.
        </Alert>
      )}

      <Group justify="space-between">
        <Text size="xs" c="dimmed">
          {lastChanged ? `Last changed ${showDate(lastChanged)}` : 'Not set yet'}
        </Text>
        <Group gap="sm">
          {dirty && (
            <Button
              variant="subtle"
              size="sm"
              onClick={() => setSelected(declaredIds)}
            >
              Discard changes
            </Button>
          )}
          <Button
            size="sm"
            loading={saving}
            disabled={!dirty}
            leftSection={<IconBuildingWarehouse size={16} />}
            onClick={() =>
              removed.length > 0 ? setConfirmingRemoval(true) : persist()
            }
          >
            Save operations
          </Button>
        </Group>
      </Group>

      {/* Removal is the one direction that takes something away, so it is
          spelled out rather than saved on a single click. */}
      <Modal
        opened={confirmingRemoval}
        onClose={() => setConfirmingRemoval(false)}
        title="Remove from your operations?"
        centered
      >
        <Stack gap="md">
          <Text size="sm">
            You are removing{' '}
            <Text span fw={600}>
              {removedNames.join(', ')}
            </Text>
            .
          </Text>
          <Text size="sm" c="dimmed">
            You will no longer be offered a new application of that type.
            Applications already filed carry on as they are, and licences
            already issued to you stay valid and can still be renewed.
          </Text>
          <ModalFooter gap="sm">
            <Button
              variant="default"
              onClick={() => setConfirmingRemoval(false)}
            >
              Cancel
            </Button>
            <Button color="orange" loading={saving} onClick={persist}>
              Remove and save
            </Button>
          </ModalFooter>
        </Stack>
      </Modal>
    </Stack>
  );
}
