import { useState, useMemo, useCallback, useLayoutEffect, useRef } from "react";
import { Check, ChevronsUpDown, Sparkles, Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { badgeVariants } from "@/components/ui/badge";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import type { FieldOption } from "./types";
import type { TaxonomySuggestion } from "@/components/product-import/steps/ValidationStep/store/types";

interface ColorOption extends FieldOption {
  hex?: string;
  hexColor?: string;
  hex_color?: string;
}

function getHex(opt: ColorOption): string | undefined {
  const raw = opt.hex ?? opt.hexColor ?? opt.hex_color;
  if (!raw) return undefined;
  return raw.startsWith("#") ? raw : `#${raw}`;
}

function isWhite(hex: string) {
  return /^#?f{3,6}$/i.test(hex);
}

function TruncatedBadge({ label, hex }: { label: string; hex?: string }) {
  const textRef = useRef<HTMLSpanElement>(null);
  const [isTruncated, setIsTruncated] = useState(false);

  useLayoutEffect(() => {
    const el = textRef.current;
    if (el) setIsTruncated(el.scrollWidth > el.clientWidth);
  }, [label]);

  return (
    <Tooltip open={isTruncated ? undefined : false}>
      <TooltipTrigger asChild>
        <span className={cn(badgeVariants({ variant: "secondary" }), "text-[11px] py-0 px-1.5 gap-1 font-normal max-w-full")}>
          {hex && (
            <span
              className={cn("inline-block h-2.5 w-2.5 rounded-full shrink-0", isWhite(hex) && "border border-black")}
              style={{ backgroundColor: hex }}
            />
          )}
          <span
            ref={textRef}
            className="overflow-hidden whitespace-nowrap"
            style={{ direction: "rtl", textOverflow: "ellipsis" }}
          >
            {label}
          </span>
        </span>
      </TooltipTrigger>
      <TooltipContent>{label}</TooltipContent>
    </Tooltip>
  );
}

export function EditableMultiSelect({
  options,
  value,
  onChange,
  label,
  placeholder,
  searchPlaceholder,
  showColors,
  suggestions,
  isLoadingSuggestions,
  onOpen,
}: {
  options: FieldOption[];
  value: string[];
  onChange: (val: string[]) => void;
  label?: string;
  placeholder?: string;
  searchPlaceholder?: string;
  showColors?: boolean;
  suggestions?: TaxonomySuggestion[];
  isLoadingSuggestions?: boolean;
  onOpen?: () => void;
}) {
  const [open, setOpen] = useState(false);

  const handleOpenChange = useCallback((isOpen: boolean) => {
    setOpen(isOpen);
    if (isOpen) onOpen?.();
  }, [onOpen]);

  const selectedLabels = useMemo(() => {
    return value.map((v) => {
      const opt = options.find((o) => String(o.value) === String(v));
      const hex = showColors && opt ? getHex(opt as ColorOption) : undefined;
      return { value: v, label: opt?.label ?? v, hex };
    });
  }, [value, options, showColors]);

  const handleSelect = useCallback(
    (optValue: string) => {
      if (value.includes(optValue)) {
        onChange(value.filter((v) => v !== optValue));
      } else {
        onChange([...value, optValue]);
      }
    },
    [value, onChange]
  );

  const handleWheel = useCallback((e: React.WheelEvent<HTMLDivElement>) => {
    e.stopPropagation();
    e.currentTarget.scrollTop += e.deltaY;
  }, []);

  // Read-only display when closed
  if (!open) {
    return (
      <button
        type="button"
        onClick={() => handleOpenChange(true)}
        className={cn(
          "flex flex-col h-auto w-full rounded-md border border-muted-foreground/50 bg-transparent px-3 py-1 text-sm text-left",
          "hover:border-input hover:bg-muted/50 transition-colors",
        )}
      >
        {label && (
          <span className="text-muted-foreground text-xs mb-0.5">{label}</span>
        )}
        {selectedLabels.length === 0 ? (
          <span className="text-muted-foreground truncate">
            {placeholder ?? "—"}
          </span>
        ) : (
          <span className="flex flex-wrap gap-1 w-full">
            {selectedLabels.map((s) => (
              <TruncatedBadge key={s.value} label={s.label} hex={s.hex} />
            ))}
          </span>
        )}
      </button>
    );
  }

  return (
    <div>
      {label && (
        <span className="text-xs text-muted-foreground mb-1 block">{label}</span>
      )}
      <Popover open={open} onOpenChange={handleOpenChange}>
        <PopoverTrigger asChild>
          <Button
            variant="outline"
            role="combobox"
            className={cn(
              "h-8 w-full justify-between text-sm font-normal",
              selectedLabels.length === 0 && "text-muted-foreground"
            )}
          >
            <span className="truncate">
              {selectedLabels.length === 0
                ? placeholder ?? "Select..."
                : `${selectedLabels.length} selected`}
            </span>
            <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </Button>
        </PopoverTrigger>
        <PopoverContent
          className="w-[--radix-popover-trigger-width] p-0"
          align="start"
        >
          <Command>
            <CommandInput placeholder={searchPlaceholder ?? "Search..."} />
            <CommandList>
              <CommandEmpty>No results.</CommandEmpty>
              <div
                className="max-h-[250px] overflow-y-auto overscroll-contain"
                onWheel={handleWheel}
              >
                {/* Selected items pinned to top */}
                {value.length > 0 && (
                  <CommandGroup>
                    <div className="flex items-center gap-2 px-2 py-1.5 text-xs font-medium text-green-600 dark:text-green-400 bg-green-50/80 dark:bg-green-950/40 border-b border-green-100 dark:border-green-900">
                      <Check className="h-3 w-3" />
                      <span>Selected ({value.length})</span>
                    </div>
                    {value.map((selectedVal) => {
                      const opt = options.find(
                        (o) => String(o.value) === String(selectedVal)
                      ) as ColorOption | undefined;
                      const hex = showColors && opt ? getHex(opt) : undefined;
                      return (
                        <CommandItem
                          key={`sel-${selectedVal}`}
                          value={`sel-${opt?.label ?? selectedVal}`}
                          onSelect={() => handleSelect(selectedVal)}
                          className="bg-green-50/50 dark:bg-green-950/30"
                        >
                          <Check className="mr-2 h-4 w-4 opacity-100 text-green-600" />
                          {hex && (
                            <span
                              className={cn(
                                "inline-block h-3.5 w-3.5 rounded-full mr-2 shrink-0",
                                isWhite(hex) && "border border-black"
                              )}
                              style={{ backgroundColor: hex }}
                            />
                          )}
                          {opt?.label ?? selectedVal}
                        </CommandItem>
                      );
                    })}
                  </CommandGroup>
                )}

                {/* AI Suggestions section */}
                {(suggestions && suggestions.length > 0) || isLoadingSuggestions ? (
                  <CommandGroup>
                    <div className="flex items-center gap-2 px-2 py-1.5 text-xs font-medium text-purple-600 dark:text-purple-400 bg-purple-50/80 dark:bg-purple-950/40 border-b border-purple-100 dark:border-purple-900">
                      <Sparkles className="h-3 w-3" />
                      <span>Suggested</span>
                      {isLoadingSuggestions && <Loader2 className="h-3 w-3 animate-spin" />}
                    </div>
                    {suggestions?.slice(0, 5).map((suggestion) => {
                      const isSelected = value.includes(String(suggestion.id));
                      if (isSelected) return null;
                      const similarityPercent = Math.round(suggestion.similarity * 100);
                      const opt = options.find((o) => String(o.value) === String(suggestion.id)) as ColorOption | undefined;
                      const hex = showColors && opt ? getHex(opt) : undefined;
                      return (
                        <CommandItem
                          key={`suggestion-${suggestion.id}`}
                          value={`suggestion-${suggestion.name}`}
                          onSelect={() => handleSelect(String(suggestion.id))}
                          className="bg-purple-50/30 dark:bg-purple-950/20"
                        >
                          <div className="flex items-center gap-2 min-w-0 flex-1">
                            <Check className="h-4 w-4 flex-shrink-0 opacity-0" />
                            {hex && (
                              <span
                                className={cn(
                                  "inline-block h-3.5 w-3.5 rounded-full mr-2 shrink-0",
                                  isWhite(hex) && "border border-black"
                                )}
                                style={{ backgroundColor: hex }}
                              />
                            )}
                            <span title={suggestion.fullPath || suggestion.name}>
                              {showColors ? suggestion.name : (suggestion.fullPath || suggestion.name)}
                            </span>
                          </div>
                          <span className="text-xs text-purple-500 dark:text-purple-400 ml-2 flex-shrink-0">
                            {similarityPercent}%
                          </span>
                        </CommandItem>
                      );
                    })}
                  </CommandGroup>
                ) : null}

                {/* All options (excluding already-selected) */}
                <CommandGroup
                  heading={value.length > 0 || (suggestions && suggestions.length > 0) ? "All Options" : undefined}
                >
                  {options
                    .filter((o) => !value.includes(String(o.value)))
                    .map((opt) => {
                      const hex = showColors
                        ? getHex(opt as ColorOption)
                        : undefined;
                      return (
                        <CommandItem
                          key={opt.value}
                          value={opt.label}
                          onSelect={() => handleSelect(String(opt.value))}
                        >
                          <Check className="mr-2 h-4 w-4 opacity-0" />
                          {hex && (
                            <span
                              className={cn(
                                "inline-block h-3.5 w-3.5 rounded-full mr-2 shrink-0",
                                isWhite(hex) && "border border-black"
                              )}
                              style={{ backgroundColor: hex }}
                            />
                          )}
                          {opt.label}
                        </CommandItem>
                      );
                    })}
                </CommandGroup>
              </div>
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>
    </div>
  );
}
