import {useEffect, useRef, useState} from "@wordpress/element";
import {__, sprintf} from "@wordpress/i18n";
import ToggleButton from "../../../../../../../../fields/toggle-button";
import {useSortable} from "@dnd-kit/sortable";
import {CSS} from "@dnd-kit/utilities";
import Dropdown from "../../../../../../../../fields/dropdown";
import {GROUP_ITEM_TYPES, GROUP_ITEMS_DATA, getAvailableLocationsForType, APPEAR_AFTER} from "../../_data";
import confirm from "../../../../../../../../../helpers/confirm";
import CustomDelay from "../../../settings/custom-delay";
import {
    PromptWidget,
    LinkWidget,
    MessageWidget,
    ChatHistoryWidget,
    TextWidget,
    LeadCaptureWidget
} from "./types";
import {getWidgetTitle} from "./helpers";
import {getCookie} from "../../../../../../../../../../helpers";

/**
 * Clear chatbot icon related data from session storage
 * Removes all keys starting with 'chatbot-icon-' from all chatbot objects
 */
const clearChatbotIconSessionStorage = (chatbotUuid, userUuid) => {
    try {
        const storageKey = 'lbaic.chatbots' + (userUuid ? '.' + userUuid : '');
        const storageData = localStorage.getItem(storageKey);
        if (!storageData) {
            return;
        }
        const chatbotsData = JSON.parse(storageData);

        // Remove all keys starting with 'chatbot-icon-' from each chatbot object
        if (chatbotsData && chatbotUuid in chatbotsData) {
            Object.keys(chatbotsData[chatbotUuid]).forEach(key => {
                if (key.startsWith('chatbot-icon-')) {
                    delete chatbotsData[chatbotUuid][key];
                }
            });
        }

        // Save back to sessionStorage
        localStorage.setItem(storageKey, JSON.stringify(chatbotsData));

        // Trigger action hook to notify frontend components
        LimbChatbot?.Hooks?.doAction('lbaic.chatbot.icon.widgets.storage.cleared');
    } catch (e) {
        // Silently fail if sessionStorage is not available or parsing fails
    }
};

export default function Widget({
                                   index,
                                   isLastItem,
                                   widgetItem,
                                   moveUp,
                                   moveDown,
                                   update,
                                   newWidgetItemsIds,
                                   chatbotUuid,
                                   notifications
                               }) {
    const hasMounted = useRef(false);
    const {
        attributes,
        listeners,
        setNodeRef,
        transform,
        transition,
    } = useSortable({id: widgetItem.id});
    const style = {
        transform: CSS.Transform.toString(transform),
        transition,
    };
    // States
    const [opened, setOpened] = useState(widgetItem.id === newWidgetItemsIds.at(-1));
    const [widgetItemTitle, setWidgetItemTitle] = useState('');
    const [type, setType] = useState(false);
    const [showAddNewWaitOptionPopup, setShowAddNewWaitOptionPopup] = useState(false);

    // Get available locations for this widget type
    const availableLocations = getAvailableLocationsForType(widgetItem.type);
    const showLocationField = availableLocations.length > 1;
    const currentLocation = widgetItem.locations?.[0]?.[0]?.value || (availableLocations.length > 0 ? availableLocations[0].value : 'home');

    // Show appear_after field for message widgets at chatbot_icon location
    const showWaitUntilAppear = widgetItem.type === 'message' && currentLocation === 'chatbot_icon';
    const currentWaitUntilAppear = widgetItem.appear_after ?? 0;

    const userUuid = getCookie('lbaic_chatbot_user_uuid') || '';

    /**
     * Wrapped update function that clears chatbot icon session storage
     * when a widget located at 'chatbot_icon' is changed
     */
    const wrappedUpdate = (updater) => {
        // Check if current widget is at chatbot_icon location
        const isAtChatbotIcon = currentLocation === 'chatbot_icon';

        // Call the original update function
        if (typeof updater === 'function') {
            update(prevState => {
                const newState = updater(prevState);

                // Check if widget is now at chatbot_icon after update
                if (Array.isArray(newState) && newState[index]) {
                    const updatedWidget = newState[index];
                    const updatedLocation = updatedWidget?.locations?.[0]?.[0]?.value ||
                        (getAvailableLocationsForType(updatedWidget?.type || widgetItem.type).length > 0
                            ? getAvailableLocationsForType(updatedWidget?.type || widgetItem.type)[0].value
                            : 'home');
                    const isNowAtChatbotIcon = updatedLocation === 'chatbot_icon';

                    // Clear session storage if widget is/was at chatbot_icon location
                    if (isAtChatbotIcon || isNowAtChatbotIcon) {
                        clearChatbotIconSessionStorage(chatbotUuid, userUuid);
                    }
                } else if (isAtChatbotIcon) {
                    // Widget was removed or state changed, clear if it was at chatbot_icon
                    clearChatbotIconSessionStorage(chatbotUuid, userUuid);
                }

                return newState;
            });
        } else {
            // Direct value update
            update(updater);
            if (isAtChatbotIcon) {
                clearChatbotIconSessionStorage(chatbotUuid);
            }
        }
    };

    useEffect(() => {
        // Update title
        const title = getWidgetTitle(widgetItem);
        setWidgetItemTitle(title);
    }, [widgetItem]);

    useEffect(() => {
        // Update type
        const foundType = GROUP_ITEM_TYPES.find(item => item.value === widgetItem.type);
        if (foundType) {
            setType({
                label: foundType.label,
                icon: foundType.icon,
            });
        } else {
            setType(false);
        }
        if (hasMounted.current) {
            // Update data object to keep right data only
            wrappedUpdate(prevState => prevState.map((item, i) => {
                if (i === index) {
                    return {
                        ...item,
                        data: JSON.parse(JSON.stringify(GROUP_ITEMS_DATA[item.type]))
                    };
                }
                return item;
            }));
        } else {
            hasMounted.current = true;
        }
    }, [widgetItem.type]);

    /**
     * Add custom wait delay for message widgets
     *
     * @param {number} value Custom value
     */
    const addCustomWaitDelay = (value) => {
        const customWaitTimes = JSON.parse(localStorage.getItem('lbaic.settings.chatbot.widgets.message.appear_after') || '[]');
        if (APPEAR_AFTER.findIndex(item => item.value === value) === -1 && customWaitTimes.findIndex(item => item.value === value) === -1) {
            const newOption = {
                label: sprintf(__('%d sec', 'limb-chatbot'), value),
                value: value,
            };
            customWaitTimes.push(newOption);
            APPEAR_AFTER.push(newOption);
            localStorage.setItem('lbaic.settings.chatbot.widgets.message.appear_after', JSON.stringify(customWaitTimes));
        }
        // Update widget appear_after value
        wrappedUpdate(prevState => prevState.map((item, i) => {
            if (i === index) {
                return {
                    ...item,
                    appear_after: value
                };
            }
            return item;
        }));
        setShowAddNewWaitOptionPopup(false);
    }

    /**
     * remove
     */
    const remove = async () => {
        if (await confirm(__("Are you sure you want to delete?", 'limb-chatbot'))) {
            wrappedUpdate(prevState => prevState.filter((item, i) => i !== index));
        }
    }

    return <>
        <div
            className={`lbaic-settings-table-accordion-body${!index ? ' first-of-type' : ''}${isLastItem ? ' last-of-type' : ''}`}
            style={style}>
            <div ref={setNodeRef}
                 className={`lbaic-settings-table-accordion-body-in lbaic-settings-table-accordion-summary lbaic-settings-cb-pw-table-summary lbaic-settings-cb-pw-table-summary-nested${opened ? ' active' : ''}`}>
                <div className="lbaic-settings-table-accordion-body-item lbaic-settings-cb-pw-table-actions">
                    <div className="lbaic-settings-cb-pw-table-left-actions-in">
                        <button
                            className="lbaic-settings-cb-pw-button lbaic-settings-cb-pw-button-dragable lbaic-settings-button-reset" {...listeners} {...attributes}>
                            <svg className="lbaic-settings-cb-pw-button-i" xmlns="http://www.w3.org/2000/svg"
                                 fill="none"
                                 viewBox="0 0 24 24">
                                <use href="#lbaic-settings-drag"></use>
                            </svg>
                        </button>
                        <div className="lbaic-settings-cb-pw-table-position-actions">
                            <button
                                className="lbaic-settings-cb-pw-button lbaic-settings-button-reset lbaic-settings-cb-pw-table-position-actions-item"
                                onClick={moveUp}>
                                <svg className="lbaic-settings-cb-pw-table-position-actions-i"
                                     xmlns="http://www.w3.org/2000/svg" fill="none"
                                     viewBox="0 0 8 5">
                                    <use href="#lbaic-settings-backward"/>
                                </svg>
                            </button>
                            <button
                                className="lbaic-settings-cb-pw-button lbaic-settings-button-reset lbaic-settings-cb-pw-table-position-actions-item"
                                onClick={moveDown}>
                                <svg className="lbaic-settings-cb-pw-table-position-actions-i"
                                     xmlns="http://www.w3.org/2000/svg" fill="none"
                                     viewBox="0 0 8 5">
                                    <use href="#lbaic-settings-forward"/>
                                </svg>
                            </button>
                        </div>
                    </div>
                </div>
                <div
                    className="lbaic-settings-table-accordion-body-item lbaic-settings-cb-pw-table-actions lbaic-settings-cb-pw-table-number"
                    onClick={() => setOpened(!opened)}>
                <span
                    className="lbaic-settings-table-accordion-body-label lbaic-settings-cb-pw-table-accordion-body-label">{index + 1}</span>
                </div>
                <div className="lbaic-settings-table-accordion-body-item lbaic-settings-cb-pw-table-body-item"
                     onClick={() => setOpened(!opened)}>
                <span
                    className={`lbaic-settings-table-accordion-body-label lbaic-settings-cb-pw-table-accordion-body-label${!widgetItemTitle ? ' lbaic-settings-cb-pw-table-card-body-label-null' : ''}`}
                    dangerouslySetInnerHTML={{__html: widgetItemTitle || __("no label", 'limb-chatbot')}}/>
                    <button
                        className="lbaic-settings-cb-pw-table-actions-item lbaic-settings-cb-pw-table-actions-edit lbaic-settings-cb-pw-button-primary lbaic-settings-button-reset"
                        onClick={() => setOpened(!opened)}>
                        <svg className="lbaic-settings-cb-pw-table-accordion-body-i"
                             xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
                            <use href="#lbaic-settings-edit"/>
                        </svg>
                    </button>
                </div>
                <div className="lbaic-settings-table-accordion-body-item lbaic-settings-cb-pw-table-body-item"
                     onClick={() => setOpened(!opened)}>
                    {type &&
                        <div className="lbaic-settings-cb-pw-table-actions-in">
                            <svg className='lbaic-settings-cb-pw-icon' xmlns='http://www.w3.org/2000/svg'
                                 viewBox='0 0 24 24'>
                                <use href={`#lbaic-settings-${type.icon}${opened ? '-active' : ''}`}/>
                            </svg>
                            <span
                                className="lbaic-settings-table-accordion-body-label lbaic-settings-cb-pw-table-accordion-body-label"
                                dangerouslySetInnerHTML={{__html: type.label}}/>
                        </div>}
                </div>
                <div className="lbaic-settings-table-accordion-body-item lbaic-settings-cb-pw-table-actions">
                    <div className="lbaic-settings-cb-pw-table-actions-in">
                        <ToggleButton
                            className='lbaic-settings-toggle-sm'
                            isActive={widgetItem.published}
                            onClick={() => wrappedUpdate(prevState => prevState.map((item, i) => {
                                if (i === index) {
                                    return {
                                        ...item,
                                        published: !item.published,
                                    };
                                }
                                return item;
                            }))}/>
                    </div>
                </div>
                <div className="lbaic-settings-table-accordion-body-item lbaic-settings-cb-pw-table-actions">
                    <div className="lbaic-settings-cb-pw-table-actions-in lbaic-settings-cb-pw-table-actions-nested-in">
                        <button
                            className='lbaic-settings-cb-pw-table-actions-item lbaic-settings-cb-pw-button-primary lbaic-settings-button-reset'
                            onClick={remove}>
                            <svg className="lbaic-settings-cb-pw-table-accordion-body-i"
                                 xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
                                <use href="#lbaic-settings-delete"/>
                            </svg>
                        </button>
                    </div>
                </div>
            </div>
            <div
                className={`lbaic-settings-table-accordion-body-in lbaic-settings-table-accordion-details lbaic-settings-cb-pw-table-accordion-details${opened ? ' opened' : ''}`}>
                <div className="lbaic-settings-table-accordion-body-item lbaic-settings-table-accordion-details-in">
                    <div
                        className="lbaic-settings-table-accordion-content lbaic-settings-cb-pw-table-accordion-content">
                        <div className="lbaic-settings-divider-gap-end-inner"/>
                        {showLocationField &&
                            <div className="lbaic-settings-column">
                                <div className="lbaic-settings-column-in">
                                    <Dropdown value={currentLocation}
                                              setValue={value => wrappedUpdate(prevState => prevState.map((item, i) => {
                                                  if (i === index) {
                                                      return {
                                                          ...item,
                                                          locations: [[{
                                                              param: 'screen',
                                                              operator: '===',
                                                              value: value
                                                          }]]
                                                      };
                                                  }
                                                  return item;
                                              }))}
                                              placeholder={__("Location", 'limb-chatbot')}
                                              options={availableLocations}/>
                                </div>
                                <div className="lbaic-settings-column-in"/>
                            </div>}
                        {widgetItem.type === 'prompt' && (
                            <PromptWidget
                                widgetItem={widgetItem}
                                index={index}
                                update={wrappedUpdate}
                                notifications={notifications}
                            />
                        )}
                        {widgetItem.type === 'link' && (
                            <LinkWidget
                                widgetItem={widgetItem}
                                index={index}
                                update={wrappedUpdate}
                            />
                        )}
                        {widgetItem.type === 'message' && (
                            <MessageWidget
                                widgetItem={widgetItem}
                                index={index}
                                update={wrappedUpdate}
                                notifications={notifications}
                                showWaitUntilAppear={showWaitUntilAppear}
                                currentWaitUntilAppear={currentWaitUntilAppear}
                                setShowAddNewWaitOptionPopup={setShowAddNewWaitOptionPopup}
                            />
                        )}
                        {widgetItem.type === 'chat_history' && (
                            <ChatHistoryWidget
                                widgetItem={widgetItem}
                                index={index}
                                update={wrappedUpdate}
                                notifications={notifications}
                            />
                        )}
                        {widgetItem.type === 'text' && (
                            <TextWidget
                                widgetItem={widgetItem}
                                index={index}
                                update={wrappedUpdate}
                            />
                        )}
                        {widgetItem.type === 'lead_capture' && (
                            <LeadCaptureWidget
                                widgetItem={widgetItem}
                                index={index}
                                update={wrappedUpdate}
                                notifications={notifications}
                            />
                        )}
                    </div>
                </div>
            </div>
        </div>
        {showAddNewWaitOptionPopup &&
            <CustomDelay setValue={addCustomWaitDelay} close={() => setShowAddNewWaitOptionPopup(false)}
                         notifications={notifications}/>}
    </>
}
