import { Combobox, ComboboxInput, ComboboxOption, ComboboxOptions } from '@headlessui/react';
import { useEffect, useId, useState } from 'react';
import { filterCities } from '@/lib/geo/brazilCities';
import { cn } from '@/lib/utils';

/*
 * Campos de formulário no padrão do DS (Inputs, node 263:6409): caixa branca,
 * radius md, borda gray-300 → gray-500 no foco, com LABEL FLUTUANTE (centralizado
 * quando vazio; sobe pequeno pro topo ao focar/preencher). Valor Subtitle Semibold
 * gray-600; label gray-500. Componente global (usado em 2+ features).
 */
const boxBase =
    'peer w-full rounded-md border border-gray-300 bg-white px-4 text-subtitle font-semibold text-gray-600 outline-none transition-colors focus:border-gray-500 focus:outline-none focus:ring-0 focus-visible:outline-none';

// DS (Input Text): o label pequeno no topo aparece só quando há CONTEÚDO
// (ACTIVATED/FOCUS com texto). Vazio — mesmo focado (PRESS) — mantém o
// placeholder centralizado. Por isso o float dispara em :not(:placeholder-shown),
// e NÃO no :focus.
const floatLabel =
    'pointer-events-none absolute left-4 text-body text-gray-500 transition-all ' +
    'peer-[:not(:placeholder-shown)]:top-2.5 peer-[:not(:placeholder-shown)]:translate-y-0 peer-[:not(:placeholder-shown)]:text-body-sm';

export function FloatingInput({
    label,
    type = 'text',
    required,
    value,
    onChange,
}: {
    label: string;
    type?: string;
    required?: boolean;
    value?: string;
    onChange?: (value: string) => void;
}) {
    const id = useId();
    const controlled = value !== undefined;
    return (
        <div className="relative">
            <input
                id={id}
                type={type}
                required={required}
                placeholder=" "
                className={`${boxBase} h-16 pt-6 placeholder:text-transparent`}
                {...(controlled ? { value, onChange: (e) => onChange?.(e.target.value) } : {})}
            />
            <label htmlFor={id} className={`${floatLabel} top-1/2 -translate-y-1/2`}>
                {label}
            </label>
        </div>
    );
}

export function FloatingTextarea({ label, rows = 4, required }: { label: string; rows?: number; required?: boolean }) {
    const id = useId();
    return (
        <div className="relative">
            <textarea
                id={id}
                rows={rows}
                required={required}
                placeholder=" "
                className={`${boxBase} resize-none pb-3 pt-7 placeholder:text-transparent`}
            />
            <label htmlFor={id} className={`${floatLabel} top-5`}>
                {label}
            </label>
        </div>
    );
}

export function FloatingSelect({
    label,
    placeholder,
    options,
    required,
    value,
    onChange,
    disabled,
}: {
    label: string;
    /** Texto do estado neutro (HINT). Se ausente, usa o próprio label. */
    placeholder?: string;
    options: string[];
    required?: boolean;
    value?: string;
    onChange?: (value: string) => void;
    disabled?: boolean;
}) {
    const id = useId();
    const controlled = value !== undefined;
    // Rastreia o valor mesmo quando não-controlado, para o estado "ativado"
    // (label flutuante + valor em destaque) funcionar em qualquer uso.
    const [internal, setInternal] = useState('');
    const current = controlled ? value : internal;
    const hasValue = !!current;
    return (
        <div className="relative">
            <select
                id={id}
                required={required}
                disabled={disabled}
                className={cn(
                    boxBase,
                    'ds-select h-16 pr-11',
                    // Vazio (neutro): só o placeholder centralizado (body, gray-500).
                    // Ativado (com valor): valor Subtitle + label pequeno no topo.
                    hasValue ? 'pt-6' : 'text-body font-normal text-gray-500',
                    disabled && 'cursor-not-allowed border-gray-100 bg-gray-100',
                )}
                value={current}
                onChange={(e) => {
                    if (!controlled) setInternal(e.target.value);
                    onChange?.(e.target.value);
                }}
            >
                {/* Placeholder do estado neutro (DS: HINT TEXT) — selecionável,
                    para o usuário poder voltar a "sem seleção". */}
                <option value="">{placeholder ?? label}</option>
                {options.map((o) => (
                    <option key={o} value={o}>
                        {o}
                    </option>
                ))}
            </select>
            {/* Label pequeno no topo APENAS quando ativado (com valor). */}
            {hasValue && (
                <label htmlFor={id} className="pointer-events-none absolute left-4 top-2.5 text-body-sm text-gray-500">
                    {label}
                </label>
            )}
        </div>
    );
}

export function FloatingCombobox({
    label,
    hint,
    options,
    required,
    value = '',
    onChange,
    disabled,
}: {
    label: string;
    /** Texto centralizado quando vazio (padrão: o próprio label). */
    hint?: string;
    options: string[];
    required?: boolean;
    value?: string;
    onChange?: (value: string) => void;
    disabled?: boolean;
}) {
    const id = useId();
    const [query, setQuery] = useState('');
    const neutralHint = hint ?? label;
    const filtered = filterCities(options, query);
    const activated = !!value || !!query.trim();

    // Troca de estado → nova lista de municípios; limpa o texto de busca.
    useEffect(() => {
        setQuery('');
    }, [options]);

    return (
        <Combobox
            value={value}
            onChange={(selected) => {
                onChange?.(selected ?? '');
                setQuery('');
            }}
            disabled={disabled}
        >
            <div className="relative">
                <ComboboxInput
                    id={id}
                    required={required && !disabled}
                    autoComplete="off"
                    displayValue={() => (query !== '' ? query : value)}
                    onChange={(event) => {
                        setQuery(event.target.value);
                        if (value) {
                            onChange?.('');
                        }
                    }}
                    className={cn(
                        boxBase,
                        'h-16 placeholder:text-transparent',
                        activated
                            ? 'pt-6 text-subtitle font-semibold text-gray-600'
                            : 'text-transparent caret-gray-500',
                        disabled && 'cursor-not-allowed border-gray-100 bg-gray-100',
                    )}
                    placeholder=" "
                />
                {!activated && (
                    <span
                        className={cn(
                            'pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-body font-normal text-gray-500',
                            disabled && 'text-gray-400',
                        )}
                    >
                        {neutralHint}
                    </span>
                )}
                {activated && (
                    <label htmlFor={id} className="pointer-events-none absolute left-4 top-2.5 text-body-sm text-gray-500">
                        {label}
                    </label>
                )}
                {!disabled && (
                    <ComboboxOptions
                        portal
                        anchor="bottom start"
                        className="z-[110] max-h-60 w-[var(--input-width)] overflow-auto rounded-md border border-gray-300 bg-white py-1 shadow-lg [--anchor-gap:4px] empty:invisible"
                    >
                        {filtered.length === 0 ? (
                            <div className="px-4 py-2 text-body-sm text-gray-500">Nenhuma cidade encontrada</div>
                        ) : (
                            filtered.map((city) => (
                                <ComboboxOption
                                    key={city}
                                    value={city}
                                    className="cursor-pointer px-4 py-2.5 text-subtitle font-semibold text-gray-600 data-focus:bg-gray-100"
                                >
                                    {city}
                                </ComboboxOption>
                            ))
                        )}
                    </ComboboxOptions>
                )}
            </div>
        </Combobox>
    );
}
