import {
  Alert,
  Box,
  Combobox,
  Group,
  Input,
  InputBase,
  Paper,
  Select,
  Text,
  Title,
  useCombobox,
} from "@mantine/core";
import {
  AlertTriangle,
  Check,
  CheckCircle2,
  Info,
  Loader,
  XCircle,
} from "lucide-react";
import type { ReactNode } from "react";
import { useMemo } from "react";
import type {
  ControllerRenderProps,
  FieldError as RhfFieldError,
} from "react-hook-form";
import type { BookingFormInputValues } from "./schema";

// Brand tokens (kept local so the form reads consistently with the booking
// detail page and the scheduling step).
const INK = "#10202F";
const MUTED = "#6B7C8E";
const GREEN = "#0EA371";
const GREEN_DARK = "#0A6F4D";
const BORDER = "#E6ECF2";

export function OptionFieldError({ error }: { error?: { message?: string } }) {
  if (!error?.message) return null;
  return (
    <Text size="xs" c="red" mt={6}>
      {error.message}
    </Text>
  );
}

/**
 * Premium selectable option card with an icon tile, title, and description.
 * Pass `icon`/`iconBg`/`iconColor` for the leading tile, or compose freely via
 * `children` (legacy callers still work).
 */
export function OptionCard({
  selected,
  onClick,
  disabled,
  icon,
  iconBg = "#ECF6F1",
  iconColor = GREEN_DARK,
  title,
  description,
  children,
}: {
  selected: boolean;
  onClick?: () => void;
  disabled?: boolean;
  icon?: ReactNode;
  iconBg?: string;
  iconColor?: string;
  title?: ReactNode;
  description?: ReactNode;
  children?: ReactNode;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      disabled={disabled}
      style={{
        position: "relative",
        width: "100%",
        textAlign: "left",
        borderRadius: 16,
        padding: 18,
        cursor: disabled ? "not-allowed" : "pointer",
        transition: "all 150ms ease",
        border: `1.5px solid ${
          disabled ? BORDER : selected ? GREEN : BORDER
        }`,
        background: disabled
          ? "#F6F8FA"
          : selected
            ? "linear-gradient(135deg, #F4FBF7 0%, #FFFFFF 70%)"
            : "#FFFFFF",
        boxShadow: selected
          ? `0 0 0 1px ${GREEN}, 0 8px 20px rgba(14,163,113,0.10)`
          : "0 1px 2px rgba(16,24,40,0.04)",
        opacity: disabled ? 0.65 : 1,
      }}
      onMouseEnter={(e) => {
        if (!disabled && !selected) {
          e.currentTarget.style.borderColor = "#BFE3D2";
          e.currentTarget.style.boxShadow = "0 6px 16px rgba(16,24,40,0.07)";
        }
      }}
      onMouseLeave={(e) => {
        if (!disabled && !selected) {
          e.currentTarget.style.borderColor = BORDER;
          e.currentTarget.style.boxShadow = "0 1px 2px rgba(16,24,40,0.04)";
        }
      }}
    >
      {selected && !disabled && (
        <span
          style={{
            position: "absolute",
            right: 14,
            top: 14,
            display: "flex",
            height: 22,
            width: 22,
            alignItems: "center",
            justifyContent: "center",
            borderRadius: "50%",
            background: GREEN,
            boxShadow: "0 2px 6px rgba(14,163,113,0.45)",
          }}
        >
          <Check style={{ width: 13, height: 13, color: "#fff" }} strokeWidth={3} />
        </span>
      )}

      {/* Structured form (icon + title + description) */}
      {(icon || title || description) && (
        <Box>
          {icon && (
            <Box
              style={{
                marginBottom: 12,
                display: "flex",
                height: 42,
                width: 42,
                alignItems: "center",
                justifyContent: "center",
                borderRadius: 12,
                background: iconBg,
                color: iconColor,
              }}
            >
              {icon}
            </Box>
          )}
          {title && (
            <Text fz={15} fw={800} c={INK}>
              {title}
            </Text>
          )}
          {description && (
            <Text fz={12.5} c={MUTED} mt={3} style={{ lineHeight: 1.5 }}>
              {description}
            </Text>
          )}
        </Box>
      )}

      {children}
    </button>
  );
}

export function AlertBox({
  tone,
  children,
}: {
  tone: "warning" | "error" | "success" | "info";
  children: ReactNode;
}) {
  const map: Record<string, { color: string; icon: ReactNode }> = {
    warning: { color: "yellow", icon: <AlertTriangle size={16} /> },
    error: { color: "red", icon: <XCircle size={16} /> },
    success: { color: "teal", icon: <CheckCircle2 size={16} /> },
    info: { color: "blue", icon: <Info size={16} /> },
  };
  const { color, icon } = map[tone];
  return (
    <Alert color={color} icon={icon} radius="lg" fz="sm">
      {children}
    </Alert>
  );
}

export function StepLabel({ children }: { children: ReactNode }) {
  return (
    <Text
      fz={11}
      fw={700}
      tt="uppercase"
      c={MUTED}
      style={{ letterSpacing: "0.07em" }}
    >
      {children}
    </Text>
  );
}

/**
 * Card shell that wraps a step's body. Gives every step the same premium
 * surface, padding, and an optional eyebrow.
 */
export function StepCard({
  children,
  eyebrow,
}: {
  children: ReactNode;
  eyebrow?: ReactNode;
}) {
  return (
    <Paper
      radius={20}
      p={{ base: "lg", sm: 28 }}
      withBorder
      bg="white"
      style={{ borderColor: BORDER, boxShadow: "0 2px 14px rgba(16,24,40,0.04)" }}
    >
      {eyebrow}
      {children}
    </Paper>
  );
}

export function StepHeader({
  title,
  description,
  icon,
}: {
  title: string;
  description: string;
  icon?: ReactNode;
}) {
  return (
    <Group gap={14} align="flex-start" wrap="nowrap" mb={22}>
      {icon && (
        <Box
          style={{
            flexShrink: 0,
            width: 44,
            height: 44,
            borderRadius: 13,
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            background: "linear-gradient(135deg, #ECF6F1, #E4F3EC)",
            color: GREEN_DARK,
          }}
        >
          {icon}
        </Box>
      )}
      <Box>
        <Title order={3} fz={20} fw={800} c={INK} style={{ letterSpacing: "-0.01em" }}>
          {title}
        </Title>
        <Text size="sm" c={MUTED} mt={4} style={{ lineHeight: 1.5 }}>
          {description}
        </Text>
      </Box>
    </Group>
  );
}

/** Shared Mantine input styling so every field in the form matches. */
export const fieldStyles = {
  label: { fontWeight: 600, fontSize: 13, color: INK, marginBottom: 6 },
  input: { borderRadius: 10, minHeight: 44, height: 44, borderColor: BORDER },
} as const;

export function SelectField({
  field,
  error,
  label,
  placeholder,
  disabled,
  data,
  leftSection,
}: {
  field: ControllerRenderProps<BookingFormInputValues>;
  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={String(field.value) || null}
      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}
    />
  );
}

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

export function AsyncComboboxField({
  field,
  error,
  label,
  placeholder,
  options,
  isLoading,
  searchQuery,
  onSearchChange,
  onSelect,
  disabled,
}: {
  field: ControllerRenderProps<BookingFormInputValues>;
  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}
            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>
  );
}
