const { __ } = wp.i18n;
const { useState, useEffect, useContext } = wp.element;
import SafiEditor from "./SafiEditor";
import { AppContext } from "./AppContext";
import Utils from './Utils';


const AppMain = ( props ) => {
    // const [templates, setTemplates] = useState( ( [] ) );
    const [templates, setTemplates] = useState( ( SAFI.templates || [] ) );
    const [templatesScreenshots, setTemplatesScreenshots] = useState( SAFI.templates_screenshots || [] );
    const [editing, setEditing] = useState( false );
    const [saving, setSaving] = useState( false );
    const [activeID, setActiveID] = useState( -1 );

    // Drag and drop state
    const [draggedItem, setDraggedItem] = useState( null );
    const [dragOverIndex, setDragOverIndex] = useState( null );

    const isPro = useContext( AppContext );

    // console.log(Object.values(SAFI.templates))
    /**
     * Removes 'selected' and 'chosen' props, that are automatically added by ReactSortable to the list
     * @param {*} obj 
     */
    const cleanListProps = ( arr ) => {
        return arr.map( item => {
            return Utils.removeKeys( item, ['selected', 'chosen'] );
        } );
    };

    /**
     * Prevents accidental closing of the browser tab while a template is being edited
     * @param {*} showExitPrompt 
     */
    const initBeforeUnLoad = ( showExitPrompt ) => {
        window.onbeforeunload = ( event ) => {
            // Show prompt based on state
            if ( showExitPrompt ) {
                const e = event || window.event;
                e.preventDefault();
                if ( e ) {
                    e.returnValue = ''
                }
                return '';
            }
        };
    };


    // Initialize the beforeunload event listener after the resources are loaded
    window.onload = function () {
        initBeforeUnLoad( editing );
    };

    // Re-Initialize the onbeforeunload event listener
    useEffect( () => {
        initBeforeUnLoad( editing );
    }, [editing] );

    useEffect( () => {
        const theTemplate = activeID !== -1 ? templates.find( item => item.id === activeID ) : null

        //Checks template if we are on a free plan
        if ( isPro === false && theTemplate ) {

            //Checks if the template matchs a Pro template criteria
            if ( Utils.isProTemplate( theTemplate ) === true ) {
                closeEditor();
                alert( __( "This template is a Pro template and cannot be edited with your current plan.", "wpjoli-safi" ) );
                // return false;
            } else {
                setCurrentTemplate( theTemplate );
            }
        } else {
            setCurrentTemplate( theTemplate );
        }

    }, [activeID] ); //run this code when the value of template changes

    const checkTemplateCountFreePlan = () => {
        // return true;
        if ( !isPro && templates.length > 6 ) {
            alert( __( "You can create a maximum of 6 templates on the Free plan. Upgrade to Pro for unlimited templates.", "wpjoli-safi" ) );
            return false;
        }

        return true;
    }

    const newTemplate = () => {
        if ( checkTemplateCountFreePlan() === false ) {
            return;
        }

        //Sets activeID to 0 to mark it as a new template
        setActiveID( 0 );
        setEditing( true );
    }

    const editTemplate = e => {
        if ( e.target.closest( ".safi-template-control" ) !== null ) {
            return;
        }

        const template = e.target.closest( '.safi-template' );
        const templateID = template.dataset.tplId;
        if ( templateID !== -1 ) {
            setActiveID( templateID );
            setEditing( true );
        }
    };

    const [currentTemplate, setCurrentTemplate] = useState( activeID !== -1 ? templates.find( item => item.id === activeID ) : null );

    // console.log( activeID, currentTemplate );
    const handleDemoTemplateLoad = ( template ) => {
        // console.log( template );
        setCurrentTemplate( template.template );
        setActiveID( 0 ); // Set ID at 0 to make it be a new template
        setEditing( true );
    }

    const closeEditor = () => {
        setEditing( false );
        setCurrentTemplate( null );
        setActiveID( -1 );

        document.body.style.overflow = 'unset';
    };

    /**
     * 
     * @param {*} templateData 
     * @param {*} screenshot base64 png image data 
     * @returns 
     */
    async function saveTemplate( templateData, screenshot ) {
        setSaving( true );
        try {

            let response;
            //If we save from a new unsaved template
            if ( activeID === 0 ) {
                response = await doAjax( 'save', templateData, screenshot );
            }
            //For an existing template being currently edited
            else if ( activeID !== -1 ) {
                response = await doAjax( 'update', templateData, screenshot );
            }
            setSaving( false );
            return response;
        } catch ( e ) {
            setSaving( false );
            return null;
        }

    }

    const handleDuplicateTemplate = ( templateID ) => {

        if ( checkTemplateCountFreePlan() === false ) {
            return;
        }

        duplicateTemplate( templateID );
    }
    /**
     * 
     * @param {*} templateData 
     * @param {*} screenshot base64 png image data 
     * @returns 
     */
    async function duplicateTemplate( templateID ) {

        let templateData = templates.find( item => item.id == templateID )

        templateData.content.canvas.templateName = templateData.content.canvas.templateName + " (copy)";
        const stringifedTemplate = JSON.stringify( templateData.content );
        try {

            let response;
            //If we save from a new unsaved template
            if ( templateID !== 0 ) {
                response = await doAjax( 'duplicate', stringifedTemplate, null, templateID );
            }
            return response;
        } catch ( e ) {
            return null;
        }
    }


    const downloadTemplate = ( templateID ) => {

        let templateData = templates.find( item => item.id == templateID )

        const stringifedTemplate = JSON.stringify( templateData );

        const templateName = templateData.content.canvas.templateName;
        const filename = "template-" + templateID + "-" + Utils.slugify( templateName ) + ".safi.json";
        var element = document.createElement( 'a' );
        element.setAttribute( 'href', 'data:text/plain;charset=utf-8,' + encodeURIComponent( stringifedTemplate ) );
        element.setAttribute( 'download', filename );

        element.style.display = 'none';
        document.body.appendChild( element );

        element.click();

        document.body.removeChild( element );

    }

    async function handleImportTemplate( e ) {
        if ( checkTemplateCountFreePlan() === false ) {
            return;
        }

        const fileData = e.target.files[0];

        if ( typeof fileData === 'undefined' ) {
            alert( 'Please select a file.' );
            return false;
        }

        const fileReader = new FileReader();
        fileReader.onload = async function ( progressEvent ) {
            var stringData = fileReader.result;

            try {
                let response;

                response = await doAjax( 'import', stringData );

                setSaving( false );
                return response;
            } catch ( e ) {
                setSaving( false );
                return null;
            }
        }

        fileReader.readAsText( fileData );
        fileReader.addEventListener( 'error', () => {
            console.error( `Error occurred reading file: ${fileData.name}` );
        } );

    }

    /**
     * 
     * @param {*} templateData 
     * @param {*} screenshot base64 png image data 
     * @returns 
     */
    async function deleteTemplate( templateID ) {

        if ( !confirm( "Are you sure you want to delete this template ? Template data will be permanently lost and cannot be recovered." ) ) {
            return;
        }

        setSaving( true );

        try {

            let response;
            response = await doAjax( 'delete', templateID );

            setSaving( false );
            return response;
        } catch ( e ) {
            setSaving( false );
            return null;
        }

    }

    const doAjax = ( command, data, screenshot = null, templateSrcId = null ) => {

        return new Promise( ( resolve, reject ) => {
            var xhr = new XMLHttpRequest();
            var action = 'safi_templates';
            var templateStr = data;

            xhr.open( 'POST', SAFI.ajaxurl );
            xhr.responseType = 'json';
            xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8' );
            xhr.onload = function () {
                //	DONE (numeric value 4)	The data transfer has been completed or something went wrong during the transfer (e.g., infinite redirects).
                if ( xhr.readyState === 4 ) {
                    if ( xhr.status >= 200 && xhr.status < 400 ) {
                        if ( xhr.response !== null && xhr.response.success === true ) {

                            if ( command === 'save' ) {

                                const templateObj = JSON.parse( templateStr )

                                //Adds the template to the collection
                                let currentTemplates = [...templates];
                                currentTemplates = cleanListProps( currentTemplates );
                                //gets and sets the new ID locally
                                const newID = xhr.response.data.id;

                                // console.warn( templateStr );

                                currentTemplates.push( {
                                    'id': newID,
                                    'last_modified': new Date().getTime(),
                                    'name': templateObj.canvas.templateName,
                                    'content': templateObj
                                } );

                                let currentTemplatesScreenshots = { ...templatesScreenshots };
                                currentTemplatesScreenshots[newID] = "template-" + newID + ".png";

                                setTemplates( currentTemplates );
                                setTemplatesScreenshots( currentTemplatesScreenshots );
                                setActiveID( newID );
                                resolve( newID );

                            } else if ( command === 'duplicate' ) {

                                const templateObj = JSON.parse( templateStr )

                                //Adds the template to the collection
                                let currentTemplates = [...templates];
                                currentTemplates = cleanListProps( currentTemplates );
                                //gets and sets the new ID locally
                                const newID = xhr.response.data.id;

                                currentTemplates.push( {
                                    'id': newID,
                                    'last_modified': new Date().getTime(),
                                    'name': templateObj.canvas.templateName,
                                    'content': templateObj
                                } );

                                let currentTemplatesScreenshots = { ...templatesScreenshots };
                                currentTemplatesScreenshots[newID] = "template-" + newID + ".png";

                                setTemplates( currentTemplates );
                                setTemplatesScreenshots( currentTemplatesScreenshots );
                                resolve( newID );

                            } else if ( command === 'import' ) {
                                const templateObj = JSON.parse( templateStr )

                                if ( !templateObj.id || !templateObj.content ) {
                                    alert( "Invalid template" );
                                    return false;
                                }
                                //Adds the template to the collection
                                let currentTemplates = [...templates];
                                currentTemplates = cleanListProps( currentTemplates );
                                //gets and sets the new ID locally
                                const newID = templateObj.id;

                                currentTemplates.push( templateObj );
                                setTemplates( currentTemplates );
                                resolve( newID );

                            } else if ( command === 'reorder' ) {
                                if ( xhr.response.data.reordered ) {
                                    resolve( true );
                                }
                                else {
                                    reject( "Could not reorder" );
                                }

                            } else if ( command === 'update' ) {

                                const templateObj = JSON.parse( templateStr )

                                //Adds the template to the collection
                                let currentTemplates = [...templates];
                                currentTemplates = cleanListProps( currentTemplates );
                                //if backend was successfully updated
                                if ( xhr.response.data.updated == true ) {

                                    const updatedTemplate = {
                                        'id': activeID,
                                        'last_modified': new Date().getTime(),
                                        'name': templateObj.canvas.templateName,
                                        'content': templateObj
                                    };

                                    let updatedTemplateScreenshots = { ...templatesScreenshots };
                                    updatedTemplateScreenshots[activeID] = "template-" + activeID + ".png";

                                    //From the templates array, replaces the template corresponding to the active ID
                                    const updatedTemplates = currentTemplates.map( item => item.id === activeID ? updatedTemplate : item );

                                    // console.warn( updatedTemplates );
                                    setTemplates( updatedTemplates );
                                    setTemplatesScreenshots( updatedTemplateScreenshots );

                                    resolve( activeID );
                                } else {
                                    reject( 'did not update' );
                                }
                            } else if ( command === 'delete' ) {
                                //if backend was successfully updated
                                if ( xhr.response.data.deleted == true ) {

                                    let updatedTemplates = [...templates]
                                    let updatedTemplateScreenshots = { ...templatesScreenshots };

                                    const templateID = data;
                                    updatedTemplates = updatedTemplates.filter( item => item.id !== templateID );
                                    delete updatedTemplateScreenshots[templateID];

                                    setTemplates( updatedTemplates );
                                    setTemplatesScreenshots( updatedTemplateScreenshots );

                                    resolve( templateID );
                                } else {
                                    reject( 'did not delete' );
                                }
                            }

                        } else {
                            if ( xhr?.response?.data?.message != null ) {
                                alert( xhr?.response?.data?.message );
                                console.error( xhr?.response )
                            }
                            // Response error
                            reject( 'error' );
                        }
                    } else {
                        // Response error
                        reject( 'error' );
                    }
                }
            };
            xhr.onerror = function () {
                reject( 'error' );
            };

            var dataSend = ( data );

            if ( command === 'delete' ) {
                xhr.send( 'action=' + action
                    + '&nonce=' + SAFI.editor_nonce
                    + '&command=' + command
                    + '&tplid=' + data
                );
            } else if ( command === 'duplicate' ) {
                xhr.send( 'action=' + action
                    + '&nonce=' + SAFI.editor_nonce
                    + '&command=' + command
                    + '&tplid=' + templateSrcId
                    + '&data=' + encodeURIComponent( dataSend )
                );
            } else if ( command === 'import' ) {
                xhr.send( 'action=' + action
                    + '&nonce=' + SAFI.editor_nonce
                    + '&command=' + command
                    + '&data=' + encodeURIComponent( dataSend )
                );
            } else if ( command === 'reorder' ) {
                xhr.send( 'action=' + action
                    + '&nonce=' + SAFI.editor_nonce
                    + '&command=' + command
                    + '&data=' + encodeURIComponent( JSON.stringify( data ) )
                );
            } else {
                xhr.send( 'action=' + action
                    + '&nonce=' + SAFI.editor_nonce
                    + '&command=' + command
                    + '&tplid=' + activeID
                    + '&data=' + encodeURIComponent( dataSend )
                    + '&screenshot=' + encodeURIComponent( screenshot )
                );
            }
        } );
    }

    const getScreenshot = ( id ) => {

        const theTemplate = templates.find( item => item.id === id );

        const lastModified = theTemplate.last_modified || null;

        return SAFI.templates_screenshots_url + 'template-' + id + '.png' + ( lastModified ? "?" + lastModified : "" );

        if ( templatesScreenshots[id] ) {
            return SAFI.templates_screenshots_url + templatesScreenshots[id] + ( lastModified ? "?" + lastModified : "" );
        }

        return false;
    }

    const handleReorderTemplates = ( newState ) => {
        const newOrder = newState.map( item => item.id );
        setTemplates( newState );
        doAjax( 'reorder', newOrder );
    }

    // Custom drag and drop handlers
    const handleDragStart = ( e, item, index ) => {
        // Find the real index in the templates array
        const realIndex = templates.findIndex( t => t.id === item.id );
        setDraggedItem( { item, index: realIndex, displayIndex: index } );
        e.dataTransfer.effectAllowed = 'move';
        e.dataTransfer.setData( 'text/html', e.target );

        // Add dragging class for visual feedback
        e.target.classList.add( 'dragging' );
    };

    const handleDragEnd = ( e ) => {
        e.target.classList.remove( 'dragging' );
        setDraggedItem( null );
        setDragOverIndex( null );
    };

    const handleDragOver = ( e ) => {
        e.preventDefault();
        e.dataTransfer.dropEffect = 'move';
    };

    const handleDragEnter = ( e, index ) => {
        e.preventDefault();
        setDragOverIndex( index );
    };

    const handleDragLeave = ( e ) => {
        // Only clear drag over if we're actually leaving the container
        const rect = e.currentTarget.getBoundingClientRect();
        const x = e.clientX;
        const y = e.clientY;

        if ( x < rect.left || x > rect.right || y < rect.top || y > rect.bottom ) {
            setDragOverIndex( null );
        }
    };

    const handleDrop = ( e, dropDisplayIndex ) => {
        e.preventDefault();

        if ( !draggedItem || draggedItem.displayIndex === dropDisplayIndex ) {
            return;
        }

        const newTemplates = [...templates];
        const draggedRealIndex = draggedItem.index;

        // Find the real index of the drop target in the templates array
        const dropTargetItem = draggableTemplates[dropDisplayIndex];
        const dropRealIndex = templates.findIndex( t => t.id === dropTargetItem.id );

        // Remove dragged item
        const [movedItem] = newTemplates.splice( draggedRealIndex, 1 );

        // Calculate new index based on drag direction
        let insertIndex;
        if ( draggedRealIndex < dropRealIndex ) {
            // Dragging to the right (down) → insert *after* target
            insertIndex = dropRealIndex;
        } else {
            // Dragging to the left (up) → insert *before* target
            insertIndex = dropRealIndex;
        }

        // Insert the dragged item at the new index
        newTemplates.splice( insertIndex, 0, movedItem );

        handleReorderTemplates( newTemplates );
        setDraggedItem( null );
        setDragOverIndex( null );
    };



    // Filter out control elements and get only actual templates for drag/drop
    const draggableTemplates = templates.filter( item => item.id !== "00000000" );

    return (
        <div id="safi">
            <div className="" style={{ "position": "relative" }}>
                <h2 className="safi-title-big">Templates</h2>
            </div>
            {
                templates.length === 1 &&
                <div className="safi-tpl-info">
                    <span><span className="dashicons dashicons-warning" style={{ marginRight: "5px" }}></span>{__( "You have no template yet ! Start creating a new template of import a template using the buttons below.", "wpjoli-safi" )}</span>
                </div>
            }
            <div id="safi-templates">
                <div id="safi-template-list">
                    {draggableTemplates.map( ( item, index ) => {
                        const thumbnail = getScreenshot( item.id );
                        const isDragOver = dragOverIndex === index;
                        const isDragging = draggedItem && draggedItem.displayIndex === index;

                        return (
                            <div
                                className={`safi-template ${isDragOver ? 'drag-over' : ''} ${isDragging ? 'dragging' : ''}`}
                                data-tpl-id={item.id}
                                key={item.id}
                                draggable={true}
                                onDragStart={( e ) => handleDragStart( e, item, index )}
                                onDragEnd={handleDragEnd}
                                onDragOver={handleDragOver}
                                onDragEnter={( e ) => handleDragEnter( e, index )}
                                onDragLeave={handleDragLeave}
                                onDrop={( e ) => handleDrop( e, index )}
                                onClick={editTemplate}
                                style={item.id === "00000000" ? { display: "none" } : null}
                            >
                                <div className="safi-template-content transition">
                                    <div className="safi-template-body">
                                        {thumbnail &&
                                            <img draggable={false} src={thumbnail} alt="" />
                                        }
                                    </div>
                                    <div className="safi-template-controls">
                                        <div className="safi-template-control"
                                            title={__( "Download template.", "wpjoli-safi" )}
                                            onClick={() => downloadTemplate( item.id )}>
                                            <span className="dashicons dashicons-download"></span>
                                        </div>
                                        <div className="safi-template-control"
                                            title={__( "Duplicate template.", "wpjoli-safi" )}
                                            onClick={() => handleDuplicateTemplate( item.id )}>
                                            <span className="dashicons dashicons-admin-page"></span>
                                        </div>
                                        <div className="safi-template-control"
                                            title={__( "Delete template.", "wpjoli-safi" )}
                                            onClick={() => deleteTemplate( item.id )}>
                                            <span className="dashicons dashicons-trash"></span>
                                        </div>
                                    </div>
                                </div>
                                <div className="safi-template-name">
                                    <span>{item.name}</span>
                                </div>
                            </div>
                        )
                    } )}
                    <div className="safi-tpl-controls">
                        <div id="safi-new-template"
                            className="safi-btn"
                            onClick={newTemplate}>
                            <span style={{
                                fontSize: "26px",
                                position: "absolute",
                                top: "10px",
                                left: "10px",
                                borderRadius: "40px",
                                padding: "0px 2px 4px 2px",
                                background: "white",
                                color: "#8c53ff",
                            }}>+</span><span style={{
                                marginLeft: "32px"
                            }}>{__( "NEW TEMPLATE", "wpjoli-safi" )}</span>
                        </div>
                        <div id="safi-import-template" className="safi-btn">
                            <div className="input-file-container">
                                <input
                                    className="input-file"
                                    id="my-file"
                                    type="file"
                                    accept=".safi.json"
                                    onChange={handleImportTemplate}
                                />
                                <label tabindex="0" for="my-file" className="input-file-trigger">{__( "Import", "wpjoli-safi" )}</label>
                            </div>
                        </div>
                    </div>
                    <div className="safi-tpl-box transition">
                        <div id="safi-new-template"
                            className="safi-btn"
                            onClick={newTemplate}>
                            <span style={{
                                fontSize: "26px",
                                position: "absolute",
                                top: "10px",
                                left: "10px",
                                borderRadius: "40px",
                                padding: "0px 2px 4px 2px",
                                background: "white",
                                color: "#8c53ff",
                            }}>+</span><span style={{
                                marginLeft: "32px"
                            }}>{__( "NEW TEMPLATE", "wpjoli-safi" )}</span>
                        </div>
                    </div>
                </div>
            </div >

            <SafiEditor
                context="editor"
                showEditor={editing}
                template={currentTemplate}
                templateId={activeID}
                onClose={closeEditor}
                onSaveTemplate={saveTemplate}
                isSaving={saving}
                options={props.options}
                onChangeDemoTemplate={handleDemoTemplateLoad}
            />
        </div >
    );
}

export default AppMain;