import {useEffect, useState, useRef, useMemo, useCallback} from "@wordpress/element";
import {__} from "@wordpress/i18n";
import ContentBodyInner from "../../../../../containers/content/body-inner";
import ContentLoading from "../../../../../containers/content/loading";
import Container from "../../../../../containers/content/container";
import {GetDataset, RegenerateDataset} from "../../../../../../../../rest/datasets";
import {handleError, handleSuccess} from "../../../../../../../../helpers/notifications";
import LexicalEditor from "../../../../../../../fields/lexical";
import ContentFooterLayout from "../../../../../containers/content/footer/_components/layout";
import Input from "../../../../../../../fields/input";
import Description from "../../../../../../../sections/description";

export default function DatasetSourceContentEditor({datasetId, cancel, notifications}) {
    const [loading, setLoading] = useState(1);
    const [isDataFetched, setIsDataFetched] = useState(false);
    const [saving, setSaving] = useState(false);
    const [sourceContent, setSourceContent] = useState('');
    const originalSourceContentRef = useRef('');
    const [title, setTitle] = useState('');
    const originalTitleRef = useRef('');
    const [saveVersion, setSaveVersion] = useState(0); // Force hasChanges recalculation after save

    const doing = loading > 0 || saving;

    useEffect(() => {
        fetchDataset(datasetId);
    }, []);

    /**
     * Fetch dataset
     *
     * @param {number} id Dataset ID
     * @return {Promise<void>}
     */
    const fetchDataset = async (id) => {
        setLoading(prev => prev + 1);
        try {
            const res = await GetDataset(LimbChatbot.rest.url, LimbChatbot.rest.nonce, id, {
                include: ['metas']
            });
            if (res?.dataset?.id) {
                // Extract source_content from metas
                const sourceContentMeta = res.dataset.metas?.find(meta => meta.meta_key === 'source_content');
                const content = sourceContentMeta?.meta_value || '';
                setSourceContent(content);
                // Store original content for comparison
                originalSourceContentRef.current = content;

                // Extract title from dataset name
                const datasetTitle = res.dataset.name || '';
                setTitle(datasetTitle);
                // Store original title for comparison
                originalTitleRef.current = datasetTitle;

                setIsDataFetched(true);
            }
        } catch (e) {
            handleError(e, notifications.set, {
                title: __("Failed to get the source content.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please check and try again.", 'limb-chatbot'),
            });
        }
        setLoading(prev => prev - 2);
    }

    /**
     * Clean HTML by removing style, class, and other editor-specific attributes
     *
     * @param {string} html HTML string
     * @return {string} Cleaned HTML string
     */
    const cleanHtml = useCallback((html) => {
        const temp = document.createElement('div');
        temp.innerHTML = html;

        // UI-related attributes to remove
        const uiAttributes = [
            'class',
            'style',
            'id',
            'width',
            'height',
            'align',
            'valign',
            'bgcolor',
            'background',
            'border',
            'cellpadding',
            'cellspacing',
            'color',
            'face',
            'size'
        ];

        const elements = temp.querySelectorAll('*');
        elements.forEach(el => {
            uiAttributes.forEach(attr => {
                if (el.hasAttribute(attr)) {
                    el.removeAttribute(attr);
                }
            });
        });

        return temp.innerHTML;
    }, []);

    /**
     * Check if content or title has changed
     *
     * @return {boolean}
     */
    const hasChanges = useMemo(() => {
        // Check if title has changed
        const titleChanged = title.trim() !== originalTitleRef.current.trim();

        // Check if content has changed
        let contentChanged = false;
        if (sourceContent || originalSourceContentRef.current) {
            // Compare cleaned versions
            const cleanedCurrent = cleanHtml(sourceContent);
            const cleanedOriginal = cleanHtml(originalSourceContentRef.current);
            contentChanged = cleanedCurrent !== cleanedOriginal;
        }

        return titleChanged || contentChanged;
    }, [title, sourceContent, cleanHtml, saveVersion]);

    /**
     * Save source content and title
     *
     * @return {Promise<void>}
     */
    const save = async () => {
        // Validate title is not empty (required field)
        if (!title || !title.trim()) {
            handleError({
                message: __("Title can't be empty.", 'limb-chatbot')
            }, notifications.set, {
                title: __("Validation error", 'limb-chatbot'),
                description: __("Title is required and can't be empty.", 'limb-chatbot'),
            });
            return;
        }

        // Validate source content is not empty
        if (!sourceContent || !sourceContent.trim()) {
            handleError({
                message: __("Source content can't be empty.", 'limb-chatbot')
            }, notifications.set, {
                title: __("Validation error", 'limb-chatbot'),
                description: __("Content can't be empty.", 'limb-chatbot'),
            });
            return;
        }

        // Clean the HTML before sending
        const cleanedContent = cleanHtml(sourceContent);

        // Check if title has changed
        const titleChanged = title.trim() !== originalTitleRef.current.trim();

        setSaving(true);
        try {
            // Send title only if it has changed, otherwise send null
            const titleToSend = titleChanged ? title.trim() : null;

            const res = await RegenerateDataset(
                LimbChatbot.rest.url,
                LimbChatbot.rest.nonce,
                datasetId,
                cleanedContent,
                titleToSend
            );

            if (res?.dataset) {
                handleSuccess(notifications.set, {
                    title: __("Data saved successfully.", 'limb-chatbot'),
                });

                // Update original content reference to current sourceContent (what's in the editor)
                // This ensures hasChanges compares correctly after save
                originalSourceContentRef.current = sourceContent;

                // Update original title to current title (always update, not just if changed)
                originalTitleRef.current = title.trim();

                // Force hasChanges to recalculate by incrementing saveVersion
                setSaveVersion(prev => prev + 1);
            } else {
                throw new Error(__("Invalid response from server.", 'limb-chatbot'));
            }
        } catch (e) {
            handleError(e, notifications.set, {
                title: __("Failed to save changes.", 'limb-chatbot'),
                description: e.message ? __(e.message, 'limb-chatbot') : __("Please check and try again.", 'limb-chatbot'),
            });
        } finally {
            setSaving(false);
        }
    }

    return <>
        <ContentBodyInner>
            {(loading > 0 && !isDataFetched) && <ContentLoading/>}
            <Container>
                <div className="lbaic-settings-column">
                    <div className="lbaic-settings-column-in">
                        <Input
                            value={title}
                            setValue={setTitle}
                            placeholder={__("Title", 'limb-chatbot')}
                            disabled={doing}
                        />
                        <Description>{__("Edit the title of this knowledge source", 'limb-chatbot')}</Description>
                    </div>
                </div>
                <div className="lbaic-settings-column">
                    <div className="lbaic-settings-column-in">
                        <LexicalEditor
                            key={datasetId}
                            value={sourceContent}
                            setValue={setSourceContent}
                            label={__("Content", 'limb-chatbot')}
                            placeholder={__("Enter source content...", 'limb-chatbot')}
                            convertToMarkdown={false}
                        />
                        <Description>{__("Edit the content of this knowledge source.", 'limb-chatbot')} <a href="https://wpaichatbot.com/documentation/teaching-your-chatbot/adding-knowledge-to-your-chatbot/#editing-knowledge-sources" target="_blank">{__("Learn more", 'limb-chatbot')}</a></Description>
                    </div>
                </div>
            </Container>
        </ContentBodyInner>
        <ContentFooterLayout loading={doing}>
            <button
                className={`lbaic-settings-button lbaic-settings-button-center lbaic-settings-button-h-40 lbaic-settings-button-primary lbaic-settings-content-footer-actions-in${doing || !hasChanges ? ' lbaic-settings-button-disabled' : ''}`}
                onClick={() => !doing && hasChanges && save()}>
                {saving && (
                    <svg className='lbaic-settings-button-i lbaic-settings-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'>{__("Save changes", 'limb-chatbot')}</span>
            </button>
            <button
                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-content-footer-actions-end${doing ? ' lbaic-settings-button-disabled' : ''}`}
                onClick={() => !doing && cancel()}>
                <span className='lbaic-settings-button-label'>{__("Cancel", 'limb-chatbot')}</span>
            </button>
        </ContentFooterLayout>
    </>;
}

