import { useFormContext } from 'react-hook-form';
import { AnimatePresence, motion } from 'framer-motion';
import { useEffect, useState, useRef } from 'react';
import { ChevronUpDownIcon, CheckIcon } from '@heroicons/react/24/outline';
import FormError from './FormError';

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

interface FormSelectProps {
    name: string;
    label: string;
    options: Option[];
    placeholder?: string;
    className?: string
}

const ANIMATIONS = {
    dropdown: {
        initial: { opacity: 0, y: -4 },
        animate: { opacity: 1, y: 0 },
        exit: { opacity: 0, y: -4 },
        transition: { duration: 0.15 }
    },
    error: {
        initial: { opacity: 0, y: -8 },
        animate: { opacity: 1, y: 0 },
        exit: { opacity: 0, y: -8 },
        transition: { duration: 0.2 }
    }
};

export function FormSelect({ name, label, options, placeholder = '请选择', className }: FormSelectProps) {
    const [isOpen, setIsOpen] = useState(false);
    const dropdownRef = useRef<HTMLDivElement>(null);

    const {
        register,
        formState: { errors },
        watch,
        setValue,
    } = useFormContext();

    const value = watch(name);
    const error = errors[name]?.message as string;
    const selectedOption = options.find(opt => opt.value === value);

    useEffect(() => {
        const handleClickOutside = (event: MouseEvent) => {
            if (!dropdownRef.current?.contains(event.target as Node)) {
                setIsOpen(false);
            }
        };
        document.addEventListener('mousedown', handleClickOutside);
        return () => document.removeEventListener('mousedown', handleClickOutside);
    }, []);

    const containerClasses = `
    w-full rounded-md border bg-white shadow-sm
    transition-all duration-300 ease-out
    p-2 pr-8 outline-none cursor-pointer
    ${isOpen
            ? `ring-2 ring-opacity-50 ${error ? 'ring-red-200 border-red-500' : 'ring-blue-200 border-blue-500'}`
            : 'border-gray-300'
        }
    placeholder:text-gray-400
    ${className}
    `;
    return (
        <div className="space-y-2">
            <label className="block text-sm font-medium text-gray-700">
                {label}
            </label>
            <div className="relative" ref={dropdownRef}>
                <input type="hidden" {...register(name)} />
                <div
                    className={containerClasses}
                    onClick={() => setIsOpen(!isOpen)}
                >
                    {selectedOption?.label || <span className="text-gray-400">{placeholder}</span>}
                </div>

                <ChevronUpDownIcon
                    className={`absolute right-2 top-1/2 -translate-y-1/2 w-5 h-5 
            text-gray-400 transition-transform duration-200 
            ${isOpen ? 'transform rotate-180' : ''}`}
                />

                <AnimatePresence>
                    {isOpen && (
                        <motion.div {...ANIMATIONS.dropdown}
                            className="absolute z-10 w-full mt-1 bg-white rounded-md 
                shadow-lg border border-gray-200 max-h-60 overflow-auto"
                        >
                            {options.map((option) => (
                                <div
                                    key={option.value}
                                    className={`p-2 cursor-pointer flex items-center justify-between
                    ${value === option.value ? 'bg-blue-50 text-blue-600' : 'hover:bg-gray-50'}`}
                                    onClick={() => {
                                        setValue(name, option.value, {
                                            shouldDirty: true,
                                            shouldTouch: true,
                                            shouldValidate: true
                                        });
                                        setIsOpen(false);
                                    }}
                                >
                                    {option.label}
                                    {value === option.value && <CheckIcon className="w-4 h-4" />}
                                </div>
                            ))}
                        </motion.div>
                    )}
                </AnimatePresence>

                <FormError error={error}></FormError>
            </div>
        </div>
    );
}