'use client';

import { Badge } from '@admin/components/ui/badge';
import { Button } from '@admin/components/ui/button';
import { Input } from '@admin/components/ui/input';
import { Popover, PopoverContent, PopoverTrigger } from '@admin/components/ui/popover';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@admin/components/ui/select';
import { cn } from '@admin/utils/common';
import { Check, ChevronDown, ChevronUp, Search, X } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import { Controller, useFormContext } from 'react-hook-form';

export interface Option {
    value: string | number;
    label: string;
    disabled?: boolean;
}

interface MultiSelectFieldProps {
    name: string;
    options: Option[] | string[];
    placeholder?: string;
    disabled?: boolean;
    className?: string;
    max?: number;
    searchable?: boolean;
    searchPlaceholder?: string;
    allowCustomOptions?: boolean;
    onCreate?: (value: string) => Option;
    onSearchChange?: (searchTerm: string) => void;
    onChange?: (selectedValues: string[]) => void;
}

export const MultiSelectField = ({
    name,
    options,
    placeholder = 'Select options...',
    disabled,
    className,
    max,
    searchable = false,
    searchPlaceholder = 'Search options...',
    allowCustomOptions = false,
    onCreate,
    onSearchChange,
    onChange,
}: MultiSelectFieldProps) => {
    const { control } = useFormContext();
    const [searchTerm, setSearchTerm] = useState('');
    const [isOpen, setIsOpen] = useState(false);
    const [isSelectOpen, setIsSelectOpen] = useState(false);
    const searchInputRef = useRef<HTMLInputElement>(null);

    // Helper function to normalize options to Option[] format
    const normalizeOptions = (opts: Option[] | string[]): Option[] => {
        if (!opts || !Array.isArray(opts)) {
            return [];
        }
        return opts.map((opt) => {
            if (typeof opt === 'string') {
                return { value: opt, label: opt };
            }
            // Ensure the option has both value and label
            return {
                value: opt?.value ?? '',
                label: opt?.label ?? String(opt?.value ?? ''),
                disabled: opt?.disabled,
            };
        }).filter((opt) => opt.value !== '' && opt.label !== '');
    };

    const [dynamicOptions, setDynamicOptions] = useState<Option[]>(() => normalizeOptions(options));

    // Update dynamic options when props change
    useEffect(() => {
        setDynamicOptions(normalizeOptions(options));
    }, [options]);

    // Filter options based on search term (only when searchable is true)
    const filteredOptions = searchable
        ? dynamicOptions.filter((option) => option?.label?.toLowerCase().includes(searchTerm.toLowerCase()))
        : dynamicOptions;

    // Focus search input when popover opens (only for searchable mode)
    useEffect(() => {
        if (searchable && isOpen && searchInputRef.current) {
            setTimeout(() => searchInputRef.current?.focus(), 100);
        }
    }, [isOpen, searchable]);

    // Call onSearchChange when search term changes (only for searchable mode)
    useEffect(() => {
        if (searchable && onSearchChange) {
            onSearchChange(searchTerm);
        }
    }, [searchTerm, onSearchChange, searchable]);

    return (
        <Controller
            control={control}
            name={name}
            render={({ field }) => {
                const selectedValues = field.value || [];
                const handleSelect = (optionValue: string) => {
                    if (optionValue === '__clear_all__') {
                        field.onChange([]);
                        return;
                    }

                    if (optionValue === '__select_all__') {
                        // Toggle select all: if all are selected, clear all; otherwise select all
                        const availableOptions = dynamicOptions.filter((opt: Option) => !opt.disabled);
                        const isAllCurrentlySelected =
                            availableOptions.length > 0 && availableOptions.every((opt: Option) => selectedValues.includes(String(opt.value)));

                        if (isAllCurrentlySelected) {
                            // If all are selected, clear all
                            field.onChange([]);
                            if (onChange) onChange([]);
                        } else {
                            // Otherwise, select all available options (not exceeding max limit if set)
                            const allOptionValues = availableOptions.map((opt: Option) => String(opt.value));
                            const newValues = max ? allOptionValues.slice(0, max) : allOptionValues;
                            field.onChange(newValues);
                            if (onChange) onChange(newValues);
                        }
                        return;
                    }

                    const newValues = selectedValues.includes(optionValue)
                        ? selectedValues.filter((v: string) => v !== optionValue)
                        : max && selectedValues.length >= max
                          ? selectedValues
                          : [...selectedValues, optionValue];
                    field.onChange(newValues);
                    if (onChange) onChange(newValues);

                    // Clear search term in searchable mode
                    if (searchable) {
                        setSearchTerm('');
                    }
                };

                const handleRemoveOption = (value: string) => {
                    const newValues = selectedValues.filter((v: string) => v !== value);
                    field.onChange(newValues);
                    if (onChange) onChange(newValues);
                };

                const availableOptions = dynamicOptions || [];

                // Get selected options and limit display to first 3
                const selectedOptions = selectedValues
                    .map((value: string) => dynamicOptions.find((opt: Option) => String(opt.value) === value))
                    .filter((option: Option | undefined): option is Option => Boolean(option));

                const displayOptions = selectedOptions.slice(0, 3);
                const remainingCount = selectedOptions.length - 3;

                // Check if all available options are selected for Select All checkbox state
                const isAllSelected =
                    availableOptions.length > 0 && availableOptions.every((opt: Option) => selectedValues.includes(String(opt.value)));

                // Check if search term could be a new option (only for searchable mode)
                const canCreateOptionHere =
                    searchable &&
                    allowCustomOptions &&
                    searchTerm.trim() &&
                    !dynamicOptions.some(
                        (opt: Option) =>
                            opt.label.toLowerCase() === searchTerm.toLowerCase() || String(opt.value).toLowerCase() === searchTerm.toLowerCase(),
                    ) &&
                    !selectedValues.some((value: string) => String(value).toLowerCase() === searchTerm.toLowerCase());

                const handleCreateOption = () => {
                    if (canCreateOptionHere) {
                        try {
                            let newOption: Option;

                            if (onCreate) {
                                newOption = onCreate(searchTerm.trim());
                            } else {
                                // Default behavior: create option with value and label as the search term
                                newOption = {
                                    value: searchTerm.trim(),
                                    label: searchTerm.trim(),
                                };
                            }

                            // Check if option already exists in dynamic options
                            const optionExists = dynamicOptions.some(
                                (opt: Option) =>
                                    String(opt.value) === String(newOption.value) || opt.label.toLowerCase() === newOption.label.toLowerCase(),
                            );

                            if (!optionExists) {
                                // Add to dynamic options list only if it doesn't exist
                                setDynamicOptions((prev) => [...prev, newOption]);
                            }

                            // Select the option (existing or new)
                            handleSelect(String(newOption.value));
                        } catch (error) {
                            console.warn('Failed to create option:', error);
                            // Still clear search term on error
                            setSearchTerm('');
                        }
                    }
                };

                if (searchable) {
                    // Searchable Mode - Render as Popover
                    return (
                        <div className="relative">
                            <Popover open={isOpen} onOpenChange={setIsOpen}>
                                <PopoverTrigger asChild>
                                    <Button
                                        variant="outline"
                                        role="combobox"
                                        aria-expanded={isOpen}
                                        className={cn(
                                            'min-h-[40px] w-full justify-between border-gray-300 text-left hover:bg-white',
                                            !selectedValues.length && 'text-muted-foreground',
                                            className,
                                        )}
                                        disabled={disabled}
                                    >
                                        <div className="flex flex-1 flex-wrap items-center gap-1">
                                            {selectedOptions.length > 0 ? (
                                                <>
                                                    {displayOptions.map((option: Option) => (
                                                        <Badge
                                                            key={option?.value}
                                                            variant="secondary"
                                                            className="gap-1 bg-brand-200 text-xs text-success hover:bg-brand-200"
                                                            onClick={(e) => {
                                                                e.stopPropagation();
                                                                handleRemoveOption(String(option?.value));
                                                            }}
                                                        >
                                                            <span>{option?.label}</span>
                                                            <X className="h-3 w-3 cursor-pointer hover:text-brand-800" />
                                                        </Badge>
                                                    ))}
                                                    {remainingCount > 0 && (
                                                        <Badge
                                                            variant="secondary"
                                                            className="cursor-pointer gap-1 bg-gray-100 text-xs text-gray-600 hover:bg-gray-200"
                                                            onClick={(e) => {
                                                                e.stopPropagation();
                                                                // handleSelect('__clear_all__');
                                                            }}
                                                        >
                                                            +{remainingCount} more
                                                            {/* <X className="h-3 w-3 cursor-pointer hover:text-red-600" /> */}
                                                        </Badge>
                                                    )}
                                                </>
                                            ) : (
                                                <span className="text-gray-500">{placeholder}</span>
                                            )}
                                        </div>
                                        {isOpen ? (
                                            <ChevronUp className="h-4 w-4 shrink-0 opacity-50" />
                                        ) : (
                                            <ChevronDown className="h-4 w-4 shrink-0 opacity-50" />
                                        )}
                                    </Button>
                                </PopoverTrigger>
                                <PopoverContent className="w-full min-w-[200px] p-0" align="start">
                                    <div className="flex items-center border-b px-3">
                                        <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
                                        <Input
                                            ref={searchInputRef}
                                            placeholder={searchPlaceholder}
                                            value={searchTerm}
                                            onChange={(e) => setSearchTerm(e.target.value)}
                                            className="border-0 focus-visible:ring-0"
                                            onKeyDown={(e) => {
                                                if (e.key === 'Enter' && canCreateOptionHere) {
                                                    e.preventDefault();
                                                    handleCreateOption();
                                                }
                                            }}
                                        />
                                    </div>
                                    <div className="max-h-60 overflow-auto">
                                        {/* Select All option - always visible when there are options */}
                                        {dynamicOptions.length > 0 && (
                                            <div
                                                className="flex cursor-pointer items-center gap-2 px-3 py-2 text-sm text-brand-600 hover:bg-brand-50"
                                                onClick={() => handleSelect('__select_all__')}
                                            >
                                                <div
                                                    className={cn(
                                                        'flex h-4 w-4 items-center justify-center rounded border-2 transition-colors',
                                                        isAllSelected ? 'border-brand-600 bg-brand-600' : 'border-brand-300 bg-brand-50',
                                                    )}
                                                >
                                                    <Check
                                                        className={cn(
                                                            'h-3 w-3 transition-opacity',
                                                            isAllSelected ? 'text-white opacity-100' : 'text-brand-600 opacity-0',
                                                        )}
                                                    />
                                                </div>
                                                <span className="font-medium">Select All</span>
                                            </div>
                                        )}
                                        {(dynamicOptions.length > 0 || selectedValues.length > 0) &&
                                            (filteredOptions.length > 0 || canCreateOptionHere) && <div className="border-t" />}

                                        {/* Create new option */}
                                        {canCreateOptionHere && (
                                            <div
                                                className="flex cursor-pointer items-center gap-2 px-3 py-2 text-sm text-success hover:bg-brand-200"
                                                onClick={handleCreateOption}
                                            >
                                                <div className="flex h-4 w-4 items-center justify-center rounded border-2 border-dashed border-brand-300 bg-brand-50">
                                                    <span className="text-xs font-bold text-success">+</span>
                                                </div>
                                                <span className="font-medium">Add "{searchTerm.trim()}"</span>
                                                <span className="ml-auto text-xs text-gray-400">Press Enter</span>
                                            </div>
                                        )}

                                        {/* Filtered options */}
                                        {filteredOptions.length > 0
                                            ? filteredOptions.map((option) => {
                                                  const isSelected = selectedValues.includes(String(option.value));
                                                  const isDisabled = Boolean(option.disabled || (max && selectedValues.length >= max && !isSelected));

                                                  return (
                                                      <div
                                                          key={option.value}
                                                          className={cn(
                                                              'flex cursor-pointer items-center gap-2 px-3 py-2 text-sm hover:bg-muted',
                                                              isDisabled && 'cursor-not-allowed opacity-50',
                                                              isSelected && 'bg-brand-50',
                                                          )}
                                                          onClick={() => !isDisabled && handleSelect(String(option.value))}
                                                      >
                                                          <div
                                                              className={cn(
                                                                  'flex h-4 w-4 items-center justify-center rounded border-2 transition-colors',
                                                                  isSelected
                                                                      ? 'border-success bg-success'
                                                                      : 'border-brand-200 bg-white hover:border-brand-200',
                                                              )}
                                                          >
                                                              <Check
                                                                  className={cn(
                                                                      'h-3 w-3 text-white transition-opacity',
                                                                      isSelected ? 'opacity-100' : 'opacity-0',
                                                                  )}
                                                              />
                                                          </div>
                                                          <span className={cn('flex-1', isSelected && 'font-medium text-success')}>
                                                              {option.label}
                                                          </span>
                                                      </div>
                                                  );
                                              })
                                            : !canCreateOptionHere &&
                                              searchTerm && (
                                                  <div className="px-3 py-2 text-sm text-muted-foreground">
                                                      {selectedValues.some(
                                                          (value: string) => String(value).toLowerCase() === searchTerm.toLowerCase(),
                                                      )
                                                          ? `"${searchTerm}" is already selected`
                                                          : `No options found for "${searchTerm}".`}
                                                      {allowCustomOptions &&
                                                          !selectedValues.some(
                                                              (value: string) => String(value).toLowerCase() === searchTerm.toLowerCase(),
                                                          ) && <span className="mt-1 block text-xs text-success">Type to add a new option</span>}
                                                  </div>
                                              )}
                                    </div>

                                    {/* Status messages */}
                                    {dynamicOptions?.length === 0 && !searchTerm && (
                                        <div className="px-3 py-2 text-sm text-muted-foreground">
                                            {allowCustomOptions ? 'Start typing to add options...' : 'No options available'}
                                        </div>
                                    )}

                                    {max && selectedValues.length >= max && (
                                        <div className="border-t bg-amber-50 px-3 py-2">
                                            <div className="flex items-center gap-2 text-xs text-amber-600">
                                                <div className="flex h-3 w-3 items-center justify-center rounded-full bg-amber-200">
                                                    <span className="text-[10px] font-bold text-amber-700">!</span>
                                                </div>
                                                Maximum limit of {max} reached
                                            </div>
                                        </div>
                                    )}
                                </PopoverContent>
                            </Popover>
                        </div>
                    );
                }

                // Non-searchable Mode - Render as Select
                return (
                    <div className="relative">
                        {/* Main Input Box */}
                        <div
                            className={cn(
                                'min-h-[40px] w-full rounded-md border border-gray-300 px-3 py-2 transition-all focus-within:border-success focus-within:ring-2 focus-within:ring-brand-200',
                                className,
                            )}
                        >
                            <div className="flex flex-wrap items-center gap-1">
                                {/* Selected Items as Badges - Show max 3 + more indicator */}
                                {selectedOptions.length > 0 ? (
                                    <>
                                        {displayOptions.map((option: Option) => (
                                            <Badge
                                                key={option?.value}
                                                variant="secondary"
                                                className="relative z-10 gap-1 bg-brand-100 text-xs text-success transition-colors hover:bg-brand-200"
                                            >
                                                <span>{option?.label}</span>
                                                <Button
                                                    type="button"
                                                    variant="ghost"
                                                    size="sm"
                                                    className="h-3 w-3 rounded-full p-0 text-success hover:bg-brand-200 hover:text-white"
                                                    onClick={(e: React.MouseEvent) => {
                                                        e.stopPropagation();
                                                        handleRemoveOption(String(option?.value));
                                                    }}
                                                    disabled={disabled}
                                                >
                                                    <X className="h-2.5 w-2.5" />
                                                </Button>
                                            </Badge>
                                        ))}
                                        {remainingCount > 0 && (
                                            <Badge
                                                variant="secondary"
                                                className="relative z-10 cursor-pointer gap-1 bg-gray-100 text-xs text-gray-600 hover:bg-gray-200"
                                            >
                                                <span>+{remainingCount} more</span>
                                                <Button
                                                    type="button"
                                                    variant="ghost"
                                                    size="sm"
                                                    className="h-3 w-3 rounded-full p-0 text-gray-600 hover:bg-gray-300 hover:text-red-600"
                                                    onClick={(e: React.MouseEvent) => {
                                                        e.stopPropagation();
                                                        // handleSelect('__clear_all__');
                                                    }}
                                                    disabled={disabled}
                                                >
                                                    {/* <X className="h-2.5 w-2.5" /> */}
                                                </Button>
                                            </Badge>
                                        )}
                                    </>
                                ) : null}

                                {/* Placeholder or Icon */}
                                {selectedValues.length === 0 ? (
                                    <span className="pointer-events-none relative z-10 min-w-[120px] flex-1 text-sm text-gray-400 select-none">
                                        {placeholder}
                                    </span>
                                ) : max && selectedValues.length >= max ? (
                                    <span className="pointer-events-none relative z-10 min-w-[120px] flex-1 text-sm text-gray-500 select-none">
                                        Max {max} selected
                                    </span>
                                ) : null}
                            </div>
                        </div>

                        {/* Chevron Icon - Always visible on the right */}
                        <div className="pointer-events-none absolute top-1/2 right-1.5 -translate-y-1/2">
                            {isSelectOpen ? <ChevronUp className="h-4 w-4 text-gray-400" /> : <ChevronDown className="h-4 w-4 text-gray-400" />}
                        </div>

                        {/* Dropdown for Adding Items */}
                        {availableOptions?.length > 0 && (
                            <Select value="" onValueChange={handleSelect} disabled={disabled} onOpenChange={setIsSelectOpen}>
                                <SelectTrigger className="absolute top-0 left-0 h-full w-full cursor-pointer border-none bg-transparent opacity-0">
                                    <SelectValue />
                                </SelectTrigger>
                                <SelectContent className="max-h-60 w-full">
                                    {/* Select All Option - always visible when there are options */}
                                    {dynamicOptions.length > 0 && (
                                        <SelectItem value="__select_all__" className="cursor-pointer text-brand-600 hover:bg-brand-50">
                                            <div className="flex w-full items-center gap-2">
                                                <div
                                                    className={cn(
                                                        'flex h-4 w-4 items-center justify-center rounded border-2 transition-colors',
                                                        isAllSelected ? 'border-brand-600 bg-brand-600' : 'border-brand-300 bg-brand-50',
                                                    )}
                                                >
                                                    <Check
                                                        className={cn(
                                                            'h-3 w-3 transition-opacity',
                                                            isAllSelected ? 'text-white opacity-100' : 'text-brand-600 opacity-0',
                                                        )}
                                                    />
                                                </div>
                                                <span className="font-medium">Select All</span>
                                            </div>
                                        </SelectItem>
                                    )}

                                    {(dynamicOptions.length > 0 || selectedValues.length > 0) && <div className="my-1 border-t"></div>}

                                    {/* Available Options */}
                                    {dynamicOptions.map((option: Option) => {
                                        const isSelected = selectedValues.includes(String(option.value));
                                        const isDisabled = Boolean(option.disabled || (max && selectedValues.length >= max && !isSelected));

                                        return (
                                            <SelectItem
                                                key={option.value}
                                                value={String(option.value)}
                                                className={cn('cursor-pointer hover:bg-brand-50', isDisabled && 'cursor-not-allowed opacity-50')}
                                                disabled={isDisabled}
                                            >
                                                <div className="flex w-full items-center gap-3">
                                                    <div
                                                        className={cn(
                                                            'flex h-4 w-4 items-center justify-center rounded border-2 transition-colors',
                                                            isSelected
                                                                ? 'border-success bg-success'
                                                                : 'border-gray-300 bg-white hover:border-success hover:bg-brand-200',
                                                        )}
                                                    >
                                                        <Check
                                                            className={cn(
                                                                'h-3 w-3 text-white transition-opacity',
                                                                isSelected ? 'opacity-100' : 'opacity-0',
                                                            )}
                                                        />
                                                    </div>
                                                    <span className="flex-1">{option.label}</span>
                                                </div>
                                            </SelectItem>
                                        );
                                    })}
                                </SelectContent>
                            </Select>
                        )}

                        {/* Status Messages */}
                        <div className="mt-2 space-y-1">
                            {/* Max limit reached message */}
                            {max && selectedValues.length >= max && (
                                <div className="flex items-center gap-1 rounded border border-amber-200 bg-amber-50 px-2 py-1 text-xs text-amber-600">
                                    <div className="flex h-3 w-3 items-center justify-center rounded-full bg-amber-200">
                                        <span className="text-[10px] font-bold text-amber-700">!</span>
                                    </div>
                                    Maximum limit reached
                                </div>
                            )}

                            {/* No options available message */}
                            {options?.length === 0 && (
                                <div className="rounded border border-gray-200 bg-gray-50 px-2 py-1 text-xs text-gray-500">No options available</div>
                            )}
                        </div>
                    </div>
                );
            }}
        />
    );
};
