import React from 'react';
import { Empty, Form, Select, Typography } from 'antd';
import type { SelectProps } from 'antd/es/select';
import type { FormItemProps } from 'antd/es/form';

interface SelectOption {
    label: string | React.ReactNode;
    value: string | number;
    disabled?: boolean;
}

interface FormSelectProps extends Omit<SelectProps, 'name'> {
    name: string | (string | number)[];
    label?: string;
    required?: boolean;
    /** Texto de ajuda (validação ou erro de carregamento). */
    help?: React.ReactNode;
    /** Texto complementar abaixo do campo (dica estática, não validação). */
    extra?: React.ReactNode;
    options?: SelectOption[];
    placeholder?: string;
    allowClear?: boolean;
    showSearch?: boolean;
    mode?: 'multiple' | 'tags';
    rules?: FormItemProps['rules'];
    /** Carregamento assíncrono das opções (pré-cadastro / API). */
    loading?: boolean;
    /** Falha ao obter opções — destaca o campo e permite retry. */
    fetchError?: boolean;
    /** Resposta 401/403 — mensagem de permissão, sem "Tentar novamente". */
    fetchForbidden?: boolean;
    onRetryFetch?: () => void;
    /** Conteúdo quando não há resultados (filtro ou lista vazia). */
    notFoundContent?: React.ReactNode;
}

export default function FormSelect({
    name,
    label,
    required = false,
    help,
    extra,
    options = [],
    placeholder = 'Selecione uma opção',
    allowClear = true,
    showSearch = false,
    mode,
    rules,
    loading = false,
    fetchError = false,
    fetchForbidden = false,
    onRetryFetch,
    notFoundContent,
    disabled: disabledProp,
    ...selectProps
}: FormSelectProps) {
    const formRules = required
        ? [{ required: true, message: `${label || 'Campo'} é obrigatório` }, ...(rules || [])]
        : rules;

    const mergedHelp =
        fetchError ? (
            fetchForbidden ? (
                <span>Sem permissão para consultar este catálogo.</span>
            ) : (
                <span>
                    Não foi possível carregar as opções.
                    {onRetryFetch ? (
                        <>
                            {' '}
                            <Typography.Link onClick={() => onRetryFetch()}>Tentar novamente</Typography.Link>
                        </>
                    ) : null}
                </span>
            )
        ) : (
            help
        );

    /** `notFoundContent={null}` força lista vazia sem ilustração (paridade pré-cadastro / compromissos). */
    const defaultNotFound =
        notFoundContent !== undefined
            ? notFoundContent
            : options.length === 0 && !loading && !fetchError
              ? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="Nenhuma opção" />
              : undefined;

    const selectDisabled = Boolean(disabledProp) || (!!fetchError && !loading);

    return (
        <Form.Item
            name={name}
            label={label}
            rules={formRules}
            help={mergedHelp}
            extra={fetchError ? undefined : extra}
            validateStatus={fetchError ? 'error' : undefined}
        >
            <Select
                placeholder={placeholder}
                allowClear={allowClear}
                showSearch={showSearch}
                mode={mode}
                loading={loading}
                disabled={selectDisabled}
                optionFilterProp={showSearch ? 'label' : undefined}
                notFoundContent={defaultNotFound}
                filterOption={
                    showSearch
                        ? (input, option) =>
                              (option?.label ?? '')
                                  .toString()
                                  .toLowerCase()
                                  .includes(input.toLowerCase())
                        : undefined
                }
                {...selectProps}
            >
                {options.map((option) => (
                    <Select.Option
                        key={option.value}
                        value={option.value}
                        label={typeof option.label === 'string' ? option.label : undefined}
                        disabled={option.disabled}
                    >
                        {option.label}
                    </Select.Option>
                ))}
            </Select>
        </Form.Item>
    );
}
