import {
  Box,
  Combobox,
  Group,
  Input,
  InputBase,
  Select,
  Stack,
  Text,
  useCombobox,
} from "@mantine/core";
import { Loader, Receipt } from "lucide-react";
import type { ReactNode } from "react";
import { useMemo } from "react";
import type {
  ControllerRenderProps,
  FieldError as RhfFieldError,
  FieldValues,
  FieldPath,
} from "react-hook-form";

// The contract wizard reuses the booking wizard's premium card chrome verbatim
// (OptionCard / StepCard / StepHeader / AlertBox / StepLabel / fieldStyles),
// plus the cargo-handling switch + tap-to-count pair used per container line.
export {
  AlertBox,
  fieldStyles,
  OptionCard,
  OptionFieldError,
  StepCard,
  StepHeader,
  StepLabel,
  ToggleRow,
  UnitCountToggles,
} from "@/pages/bookings/new-booking-form/shared";

import {
  fieldClassNames,
  fieldStyles,
} from "@/pages/bookings/new-booking-form/shared";

/**
 * Generic Select field — identical look to the booking wizard's SelectField but
 * generic over the form's value type so it works with the contract form.
 */
export function SelectField<
  TValues extends FieldValues = FieldValues,
  TName extends FieldPath<TValues> = FieldPath<TValues>,
>({
  field,
  error,
  label,
  placeholder,
  disabled,
  data,
  leftSection,
}: {
  field: ControllerRenderProps<TValues, TName>;
  error?: RhfFieldError;
  label: string;
  placeholder: string;
  disabled?: boolean;
  data: string[] | { value: string; label: string }[];
  leftSection?: ReactNode;
}) {
  return (
    <Select
      label={label}
      placeholder={placeholder}
      disabled={disabled}
      data={data}
      value={
        field.value === undefined || field.value === null || field.value === ""
          ? null
          : String(field.value)
      }
      onChange={(v) => field.onChange(v ?? "")}
      onBlur={field.onBlur}
      error={error?.message}
      allowDeselect={false}
      radius={10}
      checkIconPosition="right"
      leftSection={leftSection}
      comboboxProps={{ withinPortal: true, shadow: "md", radius: "md" }}
      styles={fieldStyles}
      classNames={fieldClassNames}
    />
  );
}

/**
 * Prominent "these are unit rates, not your bill" banner. Shown wherever the
 * customer is looking at contract pricing (review step + quotation modal) —
 * the contract quotes per-unit rates only; the payable total is computed at
 * booking from the quantities actually shipped.
 */
export function NotFinalPriceNotice() {
  return (
    <Group
      gap={13}
      align="flex-start"
      wrap="nowrap"
      px={16}
      py={14}
      style={{
        borderRadius: 14,
        border: "1.5px solid #F2DFB4",
        background: "linear-gradient(135deg, #FFF9EC 0%, #FFFDF8 75%)",
      }}
    >
      <Box
        style={{
          width: 38,
          height: 38,
          borderRadius: 11,
          flexShrink: 0,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          background: "#FBEED0",
          color: "#A9741A",
        }}
      >
        <Receipt size={18} />
      </Box>
      <Stack gap={3} style={{ minWidth: 0 }}>
        <Text fz={14} fw={700} c="#10202F">
          This is not your final price
        </Text>
        <Text fz={12.5} c="#6B7C8E" style={{ lineHeight: 1.5 }}>
          The figures below are <strong>per-unit rates</strong> for each service
          — not a total. Your payable amount is calculated on every booking from
          the quantities you actually ship, and invoiced then.
        </Text>
      </Stack>
    </Group>
  );
}

interface AsyncComboboxOption {
  value: string;
  label: string;
}

export function AsyncComboboxField<
  TValues extends FieldValues = FieldValues,
  TName extends FieldPath<TValues> = FieldPath<TValues>,
>({
  field,
  error,
  label,
  placeholder,
  options,
  isLoading,
  searchQuery,
  onSearchChange,
  onSelect,
  disabled,
}: {
  field: ControllerRenderProps<TValues, TName>;
  error?: RhfFieldError;
  label: string;
  placeholder: string;
  options: AsyncComboboxOption[];
  isLoading?: boolean;
  searchQuery: string;
  onSearchChange: (query: string) => void;
  onSelect: (value: string) => void;
  disabled?: boolean;
}) {
  const combobox = useCombobox();

  const selectedLabel = useMemo(() => {
    return options.find((opt) => opt.value === field.value)?.label || "";
  }, [field.value, options]);

  const handleSelectOption = (val: string) => {
    onSelect(val);
    combobox.closeDropdown();
  };

  return (
    <Input.Wrapper
      label={label}
      error={error?.message}
      styles={fieldStyles}
    >
      <Combobox
        store={combobox}
        disabled={disabled}
        shadow="md"
        radius="md"
        withinPortal
      >
        <Combobox.Target>
          <InputBase
            placeholder={placeholder}
            disabled={disabled}
            radius={10}
            styles={fieldStyles}
            classNames={{ input: fieldClassNames.input }}
            value={searchQuery || selectedLabel}
            onChange={(e) => {
              onSearchChange(e.currentTarget.value);
              combobox.openDropdown();
            }}
            onFocus={() => combobox.openDropdown()}
            onBlur={() => {
              field.onBlur();
              combobox.closeDropdown();
              if (!selectedLabel) onSearchChange("");
            }}
            rightSection={
              isLoading ? <Loader size={14} /> : <Combobox.Chevron />
            }
          />
        </Combobox.Target>

        <Combobox.Dropdown>
          <Combobox.Options>
            {isLoading ? (
              <Combobox.Empty>Loading contracts...</Combobox.Empty>
            ) : options.length === 0 ? (
              <Combobox.Empty>No contracts found</Combobox.Empty>
            ) : (
              options.map((option) => (
                <Combobox.Option
                  key={option.value}
                  value={option.value}
                  onClick={() => handleSelectOption(option.value)}
                >
                  {option.label}
                </Combobox.Option>
              ))
            )}
          </Combobox.Options>
        </Combobox.Dropdown>
      </Combobox>
    </Input.Wrapper>
  );
}
