import {useEffect, useRef, useState} from "@wordpress/element";
import {__} from "@wordpress/i18n";
import ContentFooter from "../../../containers/content/footer";
import {
    CreateVectorIndex,
    DeleteVectorIndex,
    GetVectorIndexes,
    UpdateVectorIndex
} from "../../../../../../rest/vectors-indexes";
import {handleError, handleSuccess, handleWarning} from "../../../../../../helpers/notifications";
import {handlePaginationAfterDeletion} from "../../../../../../helpers";
import AddEdit from "./add-edit";
import Table from "../../../../../sections/table";
import Empty from "../../../containers/content/empty";
import ContentLoading from "../../../containers/content/loading";
import ContentBodyInner from "../../../containers/content/body-inner";
import Container from "../../../containers/content/container";
import ContentFooterLayout from "../../../containers/content/footer/_components/layout";
import confirm from "../../../../../../helpers/confirm";
import Chip from "../../../../../fields/chip";
import {ConnectStorageToChatbot} from "../../../../../../helpers/rest/chatbot";

export default function KnowledgeStorages({notifications}) {
    // Actions states
    const [showLoading, setShowLoading] = useState(false);
    const [isDataFetched, setIsDataFetched] = useState(false);
    const [loading, setLoading] = useState(0);
    const [saving, setSaving] = useState(false);
    const [deleting, setDeleting] = useState(false);
    const [addingEditingStorage, setAddingEditingStorage] = useState(false);
    // Data
    const addEditStorageRef = useRef(null);
    const [allSelected, setAllSelected] = useState(false);
    const [storagesPagination, setStoragesPagination] = useState({
        page: 1,
        perPage: LimbChatbot.screen_options?.lbaic_items_per_page || 10,
        total: 0,
    });
    const [storagesOrder, setStoragesOrder] = useState({
        orderBy: 'id',
        order: 'desc',
    });
    const [storages, setStorages] = useState([]);
    const [selectedStorages, setSelectedStorages] = useState([]);
    const [selectedStorage, setSelectedStorage] = useState(null);

    useEffect(() => {
        // Detect action
        const searchParams = new URLSearchParams(window.location.search);
        const action = searchParams.get('action');
        if (action === 'add') {
            setSelectedStorage(null);
            startAddEdit();
        }
    }, []);

    useEffect(() => {
        // Fetch storages data
        fetchStorages(1, storagesPagination.perPage, storagesOrder);
    }, [storagesOrder, addingEditingStorage]);

    useEffect(() => {
        setSelectedStorages(prevState => [...prevState.filter(selectedId => storages.findIndex(item => item.id === selectedId) !== -1)]);
    }, [storages]);

    useEffect(() => {
        // If all storages ids exists in the selected list
        setAllSelected(selectedStorages.length > 0 && storages.every(item => selectedStorages.indexOf(item.id) !== -1));
    }, [storages, selectedStorages]);

    /**
     * Get storages
     */
    const fetchStorages = (page, perPage, params = {}) => {
        setLoading(prev => prev + 1);
        GetVectorIndexes(LimbChatbot.rest.url, LimbChatbot.rest.nonce, {
            page: page,
            per_page: perPage,
            orderby: params.orderBy || 'id',
            order: params.order || 'asc',
            include: ['metas', 'chatbot']
        }).then(res => {
            if (res.items?.length) {
                setStorages([...res.items]);
            } else {
                setStorages([]);
            }
            // Pagination state
            setStoragesPagination(prevState => ({
                ...prevState,
                page: page,
                total: +res.total,
            }));

            setIsDataFetched(true);
            setLoading(prev => prev - 1);
        }).catch(e => {
            setStorages([]);
            setIsDataFetched(true);
            setLoading(prev => prev - 1);
            handleError(e, notifications.set, {
                title: __("Failed to retrieve storages data.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please check your connection and try again.", 'limb-chatbot'),
            });
        });
    }

    /**
     * Add edit storage
     */
    const startAddEdit = () => {
        setShowLoading(true);
        setAddingEditingStorage(true);
    }

    /**
     * Delete selected storages
     */
    const deleteSelected = async () => {
        if (selectedStorages.length && await confirm(__("Are you sure you want to delete the selected ones?", 'limb-chatbot'))) {
            setDeleting(true);
            // Process states
            const deleted = [];
            const failed = [];
            // Delete selected storages
            for (const id of selectedStorages) {
                try {
                    // Delete single one
                    const res = await DeleteVectorIndex(LimbChatbot.rest.url, LimbChatbot.rest.nonce, id);
                    if (res) {
                        deleted.push(id);
                    } else {
                        failed.push(id);
                        handleError(res);
                    }
                } catch (e) {
                    failed.push(id);
                    handleError(e);
                }
            }
            // Update states
            setSelectedStorages(failed);

            // Handle pagination after deletion
            if (deleted.length > 0) {
                handlePaginationAfterDeletion({
                    currentItemsCount: storages.length,
                    deletedCount: deleted.length,
                    pagination: storagesPagination,
                    fetchFunction: fetchStorages,
                    order: storagesOrder,
                    setItems: setStorages,
                    setPagination: setStoragesPagination,
                    deletedIds: deleted
                });
            }
            // Check status to show
            if (failed.length) {
                // Failed to delete some of the storages
                let warningTitle = __("Failed to delete storages.", 'limb-chatbot');
                if (failed.length < selectedStorages.length) {
                    if (failed.length > 1) {
                        warningTitle = __("Failed to delete some of storages.", 'limb-chatbot');
                    } else {
                        if (selectedStorages.length > 1) {
                            warningTitle = __("Failed to delete one storage.", 'limb-chatbot');
                        } else {
                            warningTitle = __("Failed to delete the storage.", 'limb-chatbot');
                        }
                    }
                } else if (selectedStorages.length === 1) {
                    warningTitle = __("Failed to delete the storage.", 'limb-chatbot');
                }
                handleWarning({message: "These vector indexes doesn't deleted: " + failed.join(', ')}, notifications.set, {
                    title: warningTitle,
                    description: __("Please try again.", 'limb-chatbot'),
                });
            } else {
                // Success
                handleSuccess(notifications.set, {
                    title: __("Deletion completed successfully.", 'limb-chatbot'),
                });
            }
            setDeleting(false);
        }
    }

    /**
     * Save storage
     */
    const save = () => {
        const data = addEditStorageRef.current?.getDataToSave();
        if (!data) {
            // Errors are already shown
            return;
        }
        setSaving(true);
        const req = selectedStorage?.id ? UpdateVectorIndex(LimbChatbot.rest.url, LimbChatbot.rest.nonce, selectedStorage.id, data) : CreateVectorIndex(LimbChatbot.rest.url, LimbChatbot.rest.nonce, data);
        req.then(res => {
            if (res?.id) {
                if (selectedStorage?.id) {
                    // Updated
                    setStorages(prevState => prevState.map(item => {
                        if (item.id === res.id) {
                            return {
                                ...item,
                                ...res
                            }
                        } else {
                            return item;
                        }
                    }))
                } else {
                    // Added
                    setStorages(prevState => [...prevState, res]);
                    // Connect to chatbot
                    ConnectStorageToChatbot(
                        res.id,
                        data.metas?.find(meta => meta.meta_key === 'chatbot_uuid')?.meta_value,
                        notifications.set
                    );
                }
                handleSuccess(notifications.set, {
                    title: __("Data saved successfully.", 'limb-chatbot'),
                });
                setSelectedStorage(null);
                setAddingEditingStorage(false);
            } else {
                handleError({message: "Invalid response data."}, notifications.set, {
                    title: __("Failed to save storage.", 'limb-chatbot'),
                    description: __("Invalid response data received.", 'limb-chatbot') + ' ' + __("Please try again.", 'limb-chatbot'),
                });
            }
            setSaving(false);
        }).catch(e => {
            setSaving(false);
            handleError(e, notifications.set, {
                title: __("Failed to save changes.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please try again.", 'limb-chatbot'),
            });
        });
    }

    /**
     * Cancel adding/editing storage
     */
    const cancelAddingEditing = () => {
        setAddingEditingStorage(false);
        setSelectedStorage(null);
    }

    /**
     * Edit storage data
     *
     * @param {object} item Storage data
     */
    const editStorage = (item) => {
        setSelectedStorage(item);
        startAddEdit();
    }

    /**
     * Delete storage
     *
     * @param {object} storage Storage data
     * @param {number} i Storage index
     */
    const deleteStorage = async (storage, i) => {
        if (await confirm(__("Are you sure you want to delete the storage?", 'limb-chatbot'))) {
            setDeleting(true);
            try {
                const res = await DeleteVectorIndex(LimbChatbot.rest.url, LimbChatbot.rest.nonce, storage.id);
                if (res) {
                    // Handle pagination after deletion
                    handlePaginationAfterDeletion({
                        currentItemsCount: storages.length,
                        deletedCount: 1,
                        pagination: storagesPagination,
                        fetchFunction: fetchStorages,
                        order: storagesOrder,
                        setItems: setStorages,
                        setPagination: setStoragesPagination,
                        deletedIds: [storage.id]
                    });

                    handleSuccess(notifications.set, {
                        title: __("Deletion completed successfully.", 'limb-chatbot'),
                    });
                } else {
                    handleError(res, notifications.set, {
                        title: __("Failed to delete storage.", 'limb-chatbot'),
                        description: __("Please try again.", 'limb-chatbot'),
                    });
                }
            } catch (e) {
                handleError(e, notifications.set, {
                    title: __("Failed to delete storage.", 'limb-chatbot'),
                    description: e.message ? __(e.message, 'limb-chatbot') : __("Please try again.", 'limb-chatbot'),
                });
            }
            setDeleting(false);
        }
    }

    const tableStructure = {
        columns: [
            {
                id: 'vector_db_id',
                label: __("Provider", 'limb-chatbot'),
                className: false,
                render: null,
                value: {
                    className: false,
                    render: (row, index) =>
                        <div className='lbaic-settings-table-card-db-item'>
                            <svg className='lbaic-settings-table-card-db-item-i' xmlns='http://www.w3.org/2000/svg' fill='none'
                                 width='19' height='20' viewBox='0 0 19 20'>
                                <use href={`#lbaic-settings-${row.vector_db_id || 'wordpress'}`}/>
                            </svg>
                            <span className="lbaic-settings-table-card-body-label">{row.vector_db_id || 'local'}</span>
                        </div>
                },
            },
            {
                id: 'name',
                label: __("Name", 'limb-chatbot'),
                className: false,
                render: null,
                value: {
                    className: false,
                    value: (row, index) => row.name,
                },
            },
            {
                id: 'chatbot',
                label: __("Chatbot", 'limb-chatbot'),
                className: false,
                render: null,
                value: {
                    className: false,
                    render: (row, index) => {
                        // Title
                        let title;
                        if (row.chatbot) {
                            title = row.chatbot.utility?.title || __("Default Chatbot", 'limb-chatbot');
                        }
                        // Icon
                        const iconName = row.chatbot?.utility?.icon ? 'chatbot-icon-' + row.chatbot.utility.icon: undefined;

                        return <Chip label={title} iconName={iconName}/>
                    },
                },
            },
            {
                id: 'dimension',
                label: __("Dimension", 'limb-chatbot'),
                className: false,
                render: null,
                value: {
                    className: false,
                    render: (row, index) => {
                        return <Chip label={row.metas?.find(item => item.meta_key === 'dimension')?.meta_value} />;
                    },
                },
            },
            {
                id: 'metric',
                label: __("Metric", 'limb-chatbot'),
                className: false,
                render: null,
                value: {
                    className: false,
                    render: (row, index) => {
                        return <Chip label={row.metas?.find(item => item.meta_key === 'metric')?.meta_value} />;
                    },
                },
            },
            {
                id: 'actions',
                label: false,
                className: false,
                render: null,
                value: {
                    className: 'lbaic-settings-table-card-floating',
                    render: (row, index) =>
                        <div className='lbaic-settings-table-card-actions'>
                            {/*<button onClick={() => editStorage(row)}
                                    className={`lbaic-settings-table-card-actions-in lbaic-settings-table-card-actions-mis-auto lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-32 lbaic-settings-button-minimal${deleting ? ' lbaic-settings-button-disabled' : ''}`}>
                                <svg className='lbaic-settings-button-i' xmlns='http://www.w3.org/2000/svg' fill='none'
                                     viewBox='0 0 24 24'>
                                    <use href='#lbaic-settings-edit'/>
                                </svg>
                            </button>*/}
                            <button onClick={() => deleteStorage(row, index)}
                                    className={`lbaic-settings-table-card-actions-in lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-32 lbaic-settings-button-minimal${deleting ? ' lbaic-settings-button-disabled' : ''}`}>
                                <svg className='lbaic-settings-button-i' xmlns='http://www.w3.org/2000/svg' fill='none'
                                     viewBox='0 0 24 24'>
                                    <use href='#lbaic-settings-delete'/>
                                </svg>
                            </button>
                            {/*<button className='lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-32 lbaic-settings-button-primary'>
                                <svg className='lbaic-settings-button-i' xmlns='http://www.w3.org/2000/svg' fill='none'
                                     viewBox='0 0 24 24'>
                                    <use href='#lbaic-settings-sync'/>
                                </svg>
                                <span className='lbaic-settings-button-label'>Sync</span>
                            </button>*/}
                        </div>
                },
            },
        ]
    };

    return <>
        <ContentBodyInner>
            {(showLoading || (loading > 0 && !isDataFetched)) && <ContentLoading/>}
            <Container className="lbaic-settings-a-es">
                {addingEditingStorage &&
                    <AddEdit ref={addEditStorageRef} data={selectedStorage}
                             loading={loading} setLoading={setLoading} setShowLoading={setShowLoading}
                             notifications={notifications}/>}
                {!addingEditingStorage &&
                    (storages.length ? (
                            <Table
                                className='lbaic-settings-a-es-table lbaic-settings-scroll-style lbaic-settings-scroll-x lbaic-settings-table-card-kb-storage'
                                structure={tableStructure}
                                data={storages}
                                pagination={storagesPagination}
                                order={{get: storagesOrder, set: setStoragesOrder}}
                                _callback={fetchStorages}/>
                        ) : (
                            isDataFetched && (
                                <Empty title={__("No storages yet", 'limb-chatbot')}
                                       subtitle={__("Start by adding your first one", 'limb-chatbot')}
                                       icon="tab-storage-active">
                                    <div className='lbaic-settings-empty-actions'>
                                        <button onClick={startAddEdit}
                                                className='lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-40 lbaic-settings-button-primary'>
                                            <span
                                                className='lbaic-settings-button-label'>{__("Add new storage", 'limb-chatbot')}</span>
                                        </button>
                                    </div>
                                </Empty>
                            )
                        )
                    )
                }
            </Container>
        </ContentBodyInner>
        {addingEditingStorage ?
            <ContentFooter save={save} discard={cancelAddingEditing}
                           loading={loading} saving={saving}
                           discardLabel={__("Cancel", 'limb-chatbot')}/>
            :
            <ContentFooterLayout loading={loading > 0 || saving || deleting}>
                {storages.length > 0 &&
                    <>
                        <button onClick={startAddEdit}
                                className={`lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-40 lbaic-settings-button-primary lbaic-settings-content-footer-actions-in${loading > 0 || saving ? ' lbaic-settings-button-disabled' : ''}`}>
                            {saving &&
                                <svg className='lbaic-settings-button-i lbaic-settings-loading-circle lbaic-settings-button-loading-circle'
                                     xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24'>
                                    <use href='#lbaic-settings-circle'/>
                                </svg>}
                            <span className='lbaic-settings-button-label'>{__("Add storage", 'limb-chatbot')}</span>
                        </button>
                        {selectedStorages.length > 0
                            && <button onClick={deleteSelected}
                                       className={`lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-40 lbaic-settings-button-secondary lbaic-settings-content-footer-actions-in lbaic-settings-a-ftds-footer-actions-in${loading > 0 || !selectedStorages.length || deleting ? ' lbaic-settings-button-disabled' : ''}`}>
                                {deleting &&
                                    <svg className='lbaic-settings-button-i lbaic-settings-loading-circle lbaic-settings-button-loading-circle'
                                         xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24'>
                                        <use href='#lbaic-settings-circle'/>
                                    </svg>}
                                {!deleting &&
                                    <svg className='lbaic-settings-button-i' xmlns='http://www.w3.org/2000/svg' fill='none'
                                         viewBox='0 0 24 24'>
                                        <use href='#lbaic-settings-delete'/>
                                    </svg>}
                                <span className='lbaic-settings-button-label'>{__("Delete", 'limb-chatbot')}</span>
                            </button>}
                    </>}
            </ContentFooterLayout>}
    </>
}