import { useMemo } from 'react';
import { Select, Text } from '@mantine/core';
import { useQuery } from '@tanstack/react-query';

import { api } from '@/services/api';
import type { ZoneLayout } from '@/types/warehouse';

interface SlotPickerProps {
  zoneId: string;
  value: string;
  onChange: (slotId: string) => void;
  label?: string;
  disabled?: boolean;
}

/**
 * The stack levels a container may actually be put on right now.
 *
 * Only the next fillable level of each stack is offered: a box cannot stand on
 * level 2 while level 1 is empty, so listing level 3 of an empty stack would
 * only produce a rejected request. The server enforces the same rule — this
 * mirrors it so the operator never sees a 400 for a position the form offered.
 */
export function fillableLevels(layout: ZoneLayout | undefined) {
  if (!layout) return [];

  return layout.stacks
    .filter((stack) => stack.isActive && stack.status === 'ACTIVE')
    .flatMap((stack) => {
      const occupied = stack.slots
        .filter((slot) => slot.effectiveStatus === 'OCCUPIED')
        .map((slot) => slot.level);
      const top = occupied.length > 0 ? Math.max(...occupied) : 0;
      if (top >= stack.maxStackHeight) return [];

      const next = stack.slots.find(
        (slot) => slot.level === top + 1 && slot.effectiveStatus === 'AVAILABLE',
      );
      if (!next) return [];

      return [
        {
          value: next.slotId,
          label: `${stack.code} — level ${next.level}${top > 0 ? ` (on ${top} container${top > 1 ? 's' : ''})` : ' (ground)'}`,
        },
      ];
    });
}

export function SlotPicker({ zoneId, value, onChange, label = 'Stack position', disabled }: SlotPickerProps) {
  const { data, isLoading } = useQuery(
    api.warehouses.zoneLayout.queryOptions({
      input: { zoneId },
      enabled: Boolean(zoneId),
    }),
  );

  const options = useMemo(() => fillableLevels(data), [data]);

  // A zone with no stacks configured keeps plain zone-level placement — showing
  // an empty picker there would imply a choice that does not exist.
  if (!zoneId || (!isLoading && (data?.stacks.length ?? 0) === 0)) return null;

  return (
    <Select
      label={label}
      description={
        options.length === 0 && !isLoading ? (
          <Text size="xs" c="orange">
            Every stack in this zone is full or blocked — the item will be stored at zone level.
          </Text>
        ) : (
          'Leave blank to take the lowest free level automatically.'
        )
      }
      placeholder={isLoading ? 'Loading positions…' : 'Automatic (lowest free level)'}
      searchable
      clearable
      disabled={disabled || isLoading || options.length === 0}
      data={options}
      value={value || null}
      onChange={(v) => onChange(v ?? '')}
    />
  );
}

export default SlotPicker;
