'use client';

import { Label } from '@/components/ui/label';
import { cn } from '@/utils/common';
import { getErrorMessageByPropertyName } from '@/utils/schema-validator';
import { useFormContext } from 'react-hook-form';
import {
    CheckboxField,
    DateField,
    DatePickerField,
    FileField,
    MultiSelectField,
    OTPField,
    PasswordField,
    RadioField,
    SearchField,
    SelectField,
    TextareaField,
    TextField,
    ToggleField,
    type Option,
} from './fields';
import { MediaPickerField } from './fields/MediaPickerField';
import { GalleryItem } from '@/../../Website/Gallery/resources/assets/js/types';


interface BaseFieldProps {
    name: string;
    label?: string;
    placeholder?: string;
    disabled?: boolean;
    className?: string;
    labelClassName?: string;
    description?: string;
    required?: boolean;
}

interface TextFieldProps extends BaseFieldProps {
    type: 'text' | 'email' | 'url' | 'tel' | 'number';
}

interface PasswordFieldProps extends BaseFieldProps {
    type: 'password';
}

interface TextareaFieldProps extends BaseFieldProps {
    type: 'textarea';
    rows?: number;
}

interface SelectFieldProps extends BaseFieldProps {
    type: 'select';
    options: Option[] | string[] | Record<string, any>;
    searchable?: boolean;
    searchPlaceholder?: string;
}

interface MultiSelectFieldProps extends BaseFieldProps {
    type: 'multiselect';
    options: Option[] | string[] | Record<string, any>;
    max?: number;
    searchable?: boolean;
    searchPlaceholder?: string;
    allowCustomOptions?: boolean;
    onCreate?: (value: string) => Option;
    onSearchChange?: (searchTerm: string) => void;
    onChange?: (selectedValues: string[]) => void;
}

interface RadioFieldProps extends BaseFieldProps {
    type: 'radio';
    options: Option[] | string[];
    orientation?: 'horizontal' | 'vertical';
}

interface CheckboxFieldProps extends BaseFieldProps {
    type: 'checkbox';
    checkboxLabel?: string;
}

interface ToggleFieldProps extends BaseFieldProps {
    type: 'toggle';
    toggleLabel?: string;
}

interface DateFieldProps extends BaseFieldProps {
    type: 'date' | 'datetime-local' | 'time';
}

interface DatePickerFieldProps extends BaseFieldProps {
    type: 'datepicker';
    fromDate?: Date;
    toDate?: Date;
}

interface SearchFieldProps extends BaseFieldProps {
    type: 'search';
    onSearch?: (value: string) => void;
    suggestions?: string[];
}

interface OTPFieldProps extends BaseFieldProps {
    type: 'otp';
    length?: number;
}

interface FileFieldProps extends BaseFieldProps {
    type: 'file';
    accept?: string;
    multiple?: boolean;
    maxSize?: number;
    preview?: boolean;
    dragDrop?: boolean;
    currentUrl?: string;
    placeholderUrl?: string;
}

interface MediaPickerFieldProps extends BaseFieldProps {
    type: 'media-picker';
    multiple?: boolean;
    initialMedia?: GalleryItem | GalleryItem[];
    app_name?: string;
    app_module?: string;
}

type FormFieldProps =
    | TextFieldProps
    | PasswordFieldProps
    | TextareaFieldProps
    | SelectFieldProps
    | MultiSelectFieldProps
    | RadioFieldProps
    | CheckboxFieldProps
    | ToggleFieldProps
    | DateFieldProps
    | DatePickerFieldProps
    | SearchFieldProps
    | OTPFieldProps
    | FileFieldProps
    | MediaPickerFieldProps;

const FormField = (props: FormFieldProps) => {
    const {
        formState: { errors },
    } = useFormContext();

    const errorMessage = getErrorMessageByPropertyName(errors, props.name);

    const renderLabel = () => {
        if (!props.label) return null;
        return (
            <Label className={cn('text-md mb-2 block text-sm text-primary', props.labelClassName)}>
                {props.label}
                {props.required && <span className="ml-1 text-red-500">*</span>}
            </Label>
        );
    };

    const renderDescription = () => {
        if (!props.description) return null;
        return <p className="mt-4 text-sm text-gray-500">{props.description}</p>;
    };

    const renderError = () => {
        if (!errorMessage) return null;

        // Ensure we're always rendering a string
        const errorText =
            typeof errorMessage === 'string'
                ? errorMessage
                : typeof errorMessage === 'object' && errorMessage.message
                  ? errorMessage.message
                  : 'Invalid input';

        return <small className="mt-1 block text-sm text-red-500">{errorText}</small>;
    };

    const renderField = () => {
        switch (props.type) {
            case 'text':
            case 'email':
            case 'url':
            case 'tel':
            case 'number':
                return (
                    <TextField
                        name={props.name}
                        type={props.type}
                        placeholder={props.placeholder}
                        disabled={props.disabled}
                        className={props.className}
                    />
                );

            case 'password':
                return <PasswordField name={props.name} placeholder={props.placeholder} disabled={props.disabled} className={props.className} />;

            case 'textarea':
                return (
                    <TextareaField
                        name={props.name}
                        placeholder={props.placeholder}
                        disabled={props.disabled}
                        className={props.className}
                        rows={props.rows}
                    />
                );

            case 'select':
                return (
                    <SelectField
                        name={props.name}
                        options={props.options}
                        placeholder={props.placeholder}
                        disabled={props.disabled}
                        className={props.className}
                        searchable={props.searchable}
                        searchPlaceholder={props.searchPlaceholder}
                    />
                );

            case 'multiselect':
                return (
                    <MultiSelectField
                        name={props.name}
                        options={props.options}
                        placeholder={props.placeholder}
                        disabled={props.disabled}
                        className={props.className}
                        max={props.max}
                        searchable={props.searchable}
                        searchPlaceholder={props.searchPlaceholder}
                        allowCustomOptions={props.allowCustomOptions}
                        onCreate={props.onCreate}
                        onSearchChange={props.onSearchChange}
                        onChange={props.onChange}
                    />
                );

            case 'radio':
                return (
                    <RadioField
                        name={props.name}
                        options={props.options}
                        disabled={props.disabled}
                        className={props.className}
                        orientation={props.orientation}
                    />
                );

            case 'checkbox':
                return <CheckboxField name={props.name} disabled={props.disabled} className={props.className} checkboxLabel={props.checkboxLabel} />;

            case 'toggle':
                return <ToggleField name={props.name} disabled={props.disabled} className={props.className} toggleLabel={props.toggleLabel} />;

            case 'date':
            case 'datetime-local':
            case 'time':
                return (
                    <DateField
                        name={props.name}
                        type={props.type}
                        placeholder={props.placeholder}
                        disabled={props.disabled}
                        className={props.className}
                    />
                );

            case 'datepicker':
                return (
                    <DatePickerField
                        name={props.name}
                        placeholder={props.placeholder}
                        disabled={props.disabled}
                        className={props.className}
                        fromDate={props.fromDate}
                        toDate={props.toDate}
                    />
                );

            case 'search':
                return (
                    <SearchField
                        name={props.name}
                        placeholder={props.placeholder}
                        disabled={props.disabled}
                        className={props.className}
                        onSearch={props.onSearch}
                        suggestions={props.suggestions}
                    />
                );

            case 'otp':
                return <OTPField name={props.name} disabled={props.disabled} className={props.className} length={props.length} />;

            case 'file':
                return (
                    <FileField
                        name={props.name}
                        accept={props.accept}
                        multiple={props.multiple}
                        maxSize={props.maxSize}
                        disabled={props.disabled}
                        className={props.className}
                        placeholder={props.placeholder}
                        preview={props.preview}
                        dragDrop={props.dragDrop}
                        currentUrl={(props as any).currentUrl}
                        placeholderUrl={(props as any).placeholderUrl}
                    />
                );

            case 'media-picker':
                return (
                    <MediaPickerField
                        name={props.name}
                        disabled={props.disabled}
                        className={props.className}
                        placeholder={props.placeholder}
                        multiple={props.multiple}
                        initialMedia={props.initialMedia}
                        app_name={(props as any).app_name}
                        app_module={(props as any).app_module}
                    />
                );

            default:
                return null;
        }
    };

    return (
        <div className="space-y-1">
            {renderLabel()}
            {renderField()}
            {renderDescription()}
            {renderError()}
        </div>
    );
};

export default FormField;
