import {useEffect, useState} from "@wordpress/element";
import {__} from "@wordpress/i18n";
import MultiSelect from "../../multiselect";
import {handleError, handleWarning} from "../../../../helpers/notifications";
import {GetFiles} from "../../../../rest/files";
import AddNewFiles from "./components/add-new-files";
import {SUPPORTED_FILES} from "../../../pages/settings/pages/knowledge/sources/add-sources/_data";

const FILES_DEFAULT_PARAMS = {
    perPage: 10,
    orderBy: 'created_at',
    order: 'desc',
};

export default function FilesMultiSelect({
                                             filesUuids,
                                             onUpdateFilesUuids,
                                             isDataSet,
                                             aiProviderId,
                                             configId,
                                             validateField,
                                             errors,
                                             setLoading,
                                             saving,
                                             addNotification
                                         }) {
    const [files, setFiles] = useState([]);
    const [savedFiles, setSavedFiles] = useState([]);
    const [pagination, setPagination] = useState({
        page: 1,
        perPage: FILES_DEFAULT_PARAMS.perPage,
        total: 0,
    });
    const [showAddNewFilesPopup, setShowAddNewFilesPopup] = useState(false);

    /**
     * Update files list - only when data is actually set
     */
    useEffect(() => {
        if (isDataSet && aiProviderId) {
            // Reset selected files when AI provider changes
            onUpdateFilesUuids([]);
            // Saved files
            getSavedFiles(filesUuids);
            // Load files
            getFiles({
                page: 1,
                perPage: pagination.perPage,
            }, true);
        }
    }, [isDataSet, aiProviderId]);

    /**
     * Get files
     *
     * @param {object} params Query params
     * @param {boolean} reset Reset or append
     */
    const getFiles = async (params, reset = false) => {
        setLoading(prev => prev + 1);
        // Default params
        const reqParams = {
            page: params?.page || 1,
            per_page: params?.perPage || FILES_DEFAULT_PARAMS.perPage,
            orderby: FILES_DEFAULT_PARAMS.orderBy,
            order: FILES_DEFAULT_PARAMS.order,
        };
        // Add search param
        if (params?.search) {
            reqParams.search = params.search;
        }
        // Filter files by AI provider
        if (aiProviderId) {
            reqParams.related_to = aiProviderId;
        }
        try {
            // Get files
            const res = await GetFiles(LimbChatbot.rest.url, LimbChatbot.rest.nonce, reqParams);
            // Prepare options
            const items = res.items?.length ? res.items : [];
            // Update state
            if (reset) {
                setFiles([...items]);
            } else {
                setFiles(prevState => [...prevState, ...items]);
            }
            // Pagination info
            setPagination(prevState => ({
                ...prevState,
                page: reqParams.page,
                total: res.total,
            }));
        } catch (e) {
            handleError(e, addNotification, {
                title: __("Failed to get files.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please check and try again.", 'limb-chatbot'),
            });
        }
        setLoading(prev => prev - 1);
    }

    /**
     * Get saved files
     *
     * @param {string[]} uuids File UUIDs
     * @return {Promise<void>}
     */
    const getSavedFiles = async (uuids) => {
        if (!uuids?.length) {
            setSavedFiles([]);
            return;
        }
        setLoading(prev => prev + 1);
        try {
            const res = await GetFiles(LimbChatbot.rest.url, LimbChatbot.rest.nonce, {
                uuids: uuids,
            });
            if (res.items?.length) {
                setSavedFiles(res.items);
            } else {
                setSavedFiles([]);
            }
        } catch (e) {
            handleError(e, addNotification, {
                title: __("Failed to get saved files.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please check and try again.", 'limb-chatbot'),
            });
        }
        setLoading(prev => prev - 1);
    }

    /**
     * New files attached
     *
     * @param {object[]} files Files
     * @param {string[]} deletedFilesUuids Deleted files UUIDs
     */
    const handleAttachedFilesSelect = async (files, deletedFilesUuids) => {
        // Remove deleted files from saved files
        if (deletedFilesUuids?.length) {
            setSavedFiles(prevState => prevState.filter(file => !deletedFilesUuids.includes(file.uuid)));
        }
        // Keep as saved files (add new files, avoiding duplicates)
        if (files?.length) {
            setSavedFiles(prevState => {
                const existingUuids = new Set(prevState.map(f => f.uuid));
                const newFilesToAdd = files.filter(file => !existingUuids.has(file.uuid));
                return [...prevState, ...newFilesToAdd];
            });
        }
        // Add to selected files
        onUpdateFilesUuids(prevState => {
            const newUuids = [...prevState.filter(item => !deletedFilesUuids.includes(item)), ...files.map(file => file.uuid)];
            // Validate the field
            validateField(newUuids);
            // Update the field state
            return newUuids;
        });
        // Update files list - await to ensure dropdown options are refreshed
        await getFiles({
            page: 1,
            perPage: pagination.perPage,
        }, true);
        // Close popup
        setShowAddNewFilesPopup(false);
    }

    const search = async (params) => {
        return await getFiles(params, true);
    }

    const loadMore = async (params) => {
        return await getFiles(params);
    }

    const options = files.map(item => ({
        label: item.original_name,
        value: item.uuid,
    }));

    const savedValueOptions = savedFiles.map(item => ({
        label: item.original_name,
        value: item.uuid,
    }));

    return (
        <>
            <MultiSelect
                value={filesUuids}
                setValue={onUpdateFilesUuids}
                options={options}
                savedValueOptions={savedValueOptions}
                placeholder={__("Files", 'limb-chatbot')}
                searchable
                onSearch={search}
                onLoadMore={loadMore}
                onAddNew={() => {
                    setShowAddNewFilesPopup(true);
                }}
                pagination={pagination}
                setPagination={setPagination}
                validate={validateField}
                errorMessage={errors}
                disabled={saving}
            />
            {showAddNewFilesPopup && (
                <AddNewFiles
                    supportedTypes={{
                        display: [
                            SUPPORTED_FILES[aiProviderId]?.document?.display || '.pdf',
                            SUPPORTED_FILES[aiProviderId]?.image?.display
                        ].filter(Boolean).join(', '),
                        accept: [
                            SUPPORTED_FILES[aiProviderId]?.document?.accept || 'application/pdf, application/x-pdf',
                            SUPPORTED_FILES[aiProviderId]?.image?.accept
                        ].filter(Boolean).join(', ')
                    }}
                    fileMaxSize={SUPPORTED_FILES[aiProviderId]?.maxSize || 10 * 1024 * 1024}
                    aiProviderId={aiProviderId}
                    configId={configId}
                    onDone={handleAttachedFilesSelect}
                    onClose={() => setShowAddNewFilesPopup(false)}
                    addNotification={addNotification}
                />
            )}
        </>
    );
}