/**
 * Spellmatic — Gutenberg Editor Sidebar
 *
 * Adds a Spellmatic panel to the block editor sidebar with:
 *   1. "Scan This Post" button — runs Harper on the current post content
 *   2. Pre-publish check — warns about unfixed errors before publishing
 *   3. Multiple ranked suggestions per error (when available)
 *
 * Uses @wordpress/plugins, @wordpress/editor, @wordpress/data packages
 * that are already available in the block editor environment.
 *
 * Slot components are read from wp.editor (WordPress 6.6+). The wp.editPost
 * equivalents were deprecated in 6.6 and emit console deprecation warnings,
 * so they are only used as a fallback on WP < 6.6.
 */

( function( wp ) {
    'use strict';

    if ( ! wp || ! wp.plugins || ! wp.element || ! wp.data || ! wp.components ) {
        return;
    }

    // Prefer @wordpress/editor (6.6+); fall back to the deprecated
    // @wordpress/edit-post exports only when running on WP < 6.6.
    var slots = ( wp.editor && wp.editor.PluginSidebar ) ? wp.editor : wp.editPost;

    if ( ! slots || ! slots.PluginSidebar ) {
        return;
    }

    var el           = wp.element.createElement;
    var Fragment     = wp.element.Fragment;
    var useState     = wp.element.useState;
    var useEffect    = wp.element.useEffect;
    var useSelect    = wp.data.useSelect;
    var useDispatch  = wp.data.useDispatch;
    var registerPlugin      = wp.plugins.registerPlugin;
    var PluginSidebar       = slots.PluginSidebar;
    var PluginSidebarMoreMenuItem = slots.PluginSidebarMoreMenuItem;
    var PluginPrePublishPanel     = slots.PluginPrePublishPanel;
    var Button       = wp.components.Button;
    var PanelBody    = wp.components.PanelBody;
    var PanelRow     = wp.components.PanelRow;
    var Spinner      = wp.components.Spinner;
    var Icon         = wp.components.Icon;

    var config       = window.spellmaticEditor || {};
    var restUrl      = config.restUrl || '';
    var nonce        = config.nonce   || '';

    // ── Helper: strip HTML and shortcodes from content ───────────────────────
    function stripToPlainText( html ) {
        // Remove shortcodes.
        var text = html.replace( /\[\/?\w+[^\]]*\]/g, ' ' );
        // Remove HTML tags.
        var div = document.createElement( 'div' );
        div.innerHTML = text;
        return ( div.textContent || div.innerText || '' ).replace( /\s+/g, ' ' ).trim();
    }

    // ── Helper: wait for Harper WASM ─────────────────────────────────────────
    async function getHarper() {
        var deadline = Date.now() + 30000;
        while ( ! window.__spellmaticHarper ) {
            if ( Date.now() > deadline ) throw new Error( 'Harper engine not loaded.' );
            await new Promise( function( r ) { setTimeout( r, 200 ); } );
        }
        return await window.__spellmaticHarper.ready;
    }

    // ── The Sidebar Panel Component ──────────────────────────────────────────
    function SpellmaticSidebar() {
        var _state    = useState( [] );
        var errors    = _state[0];
        var setErrors = _state[1];

        var _scanning    = useState( false );
        var scanning     = _scanning[0];
        var setScanning  = _scanning[1];

        var _scanned     = useState( false );
        var scanned      = _scanned[0];
        var setScanned   = _scanned[1];

        // Get current post content from the editor store.
        var postContent = useSelect( function( select ) {
            var editor = select( 'core/editor' );
            var content = editor.getEditedPostContent() || '';
            var title   = editor.getEditedPostAttribute( 'title' ) || '';
            return title + '\n\n' + content;
        }, [] );

        async function runScan() {
            setScanning( true );
            setErrors( [] );
            setScanned( false );
            try {
                var harper    = await getHarper();
                var plainText = stripToPlainText( postContent );
                var results   = await harper.lintText( plainText );
                setErrors( results );
                setScanned( true );
            } catch ( err ) {
                console.error( 'Spellmatic editor scan error:', err );
            }
            setScanning( false );
        }

        // Build the error list UI.
        var errorItems = errors.map( function( err, i ) {
            return el( 'div', { key: i, style: {
                borderBottom: '1px solid #e0e0e0',
                padding: '8px 0',
                fontSize: '12px',
            } },
                el( 'div', { style: { display: 'flex', gap: '4px', alignItems: 'center', marginBottom: '4px' } },
                    el( 'code', { style: { background: '#fecaca', color: '#991b1b', padding: '1px 4px', borderRadius: '3px', textDecoration: 'line-through' } }, err.original ),
                    el( 'span', { style: { color: '#9ca3af' } }, '→' ),
                    el( 'code', { style: { background: '#bbf7d0', color: '#166534', padding: '1px 4px', borderRadius: '3px', fontWeight: 600 } }, err.suggestion )
                ),
                err.context ? el( 'div', { style: { color: '#6b7280', fontSize: '11px', lineHeight: '1.4' } }, err.context.substring( 0, 120 ) + ( err.context.length > 120 ? '…' : '' ) ) : null
            );
        } );

        return el( Fragment, {},
            el( PluginSidebarMoreMenuItem, { target: 'spellmatic-editor-sidebar', icon: 'editor-spellcheck' },
                'Spellmatic'
            ),
            el( PluginSidebar, {
                name: 'spellmatic-editor-sidebar',
                title: 'Spellmatic',
                icon: 'editor-spellcheck',
            },
                el( PanelBody, { title: 'Spell Check', initialOpen: true },
                    el( PanelRow, {},
                        el( Button, {
                            variant: 'primary',
                            onClick: runScan,
                            disabled: scanning,
                            style: { width: '100%', justifyContent: 'center' },
                        }, scanning ? el( Spinner, {} ) : 'Scan This Post' )
                    ),
                    scanned && errors.length === 0 ? el( 'div', {
                        style: { textAlign: 'center', padding: '16px 0', color: '#16a34a', fontWeight: 600 }
                    }, '✓ No errors found!' ) : null,
                    errors.length > 0 ? el( 'div', { style: { marginTop: '8px' } },
                        el( 'div', { style: { fontWeight: 600, fontSize: '12px', color: '#374151', marginBottom: '6px' } },
                            errors.length + ' error' + ( errors.length !== 1 ? 's' : '' ) + ' found'
                        ),
                        errorItems
                    ) : null
                )
            )
        );
    }

    // ── Pre-publish check panel ──────────────────────────────────────────────
    function SpellmaticPrePublish() {
        var _state    = useState( null );
        var result    = _state[0];
        var setResult = _state[1];

        var _scanning    = useState( false );
        var scanning     = _scanning[0];
        var setScanning  = _scanning[1];

        var _dismissed   = useState( false );
        var dismissed    = _dismissed[0];
        var setDismissed = _dismissed[1];

        var postContent = useSelect( function( select ) {
            var editor = select( 'core/editor' );
            return ( editor.getEditedPostAttribute( 'title' ) || '' ) + '\n\n' + ( editor.getEditedPostContent() || '' );
        }, [] );

        var editorDispatch = useDispatch( 'core/editor' );
        var publishGateActive = config.publishGate || false;

        // Auto-scan on mount.
        useEffect( function() {
            var cancelled = false;
            setScanning( true );
            ( async function() {
                try {
                    var harper = await getHarper();
                    var text   = stripToPlainText( postContent );
                    var errors = await harper.lintText( text );
                    if ( ! cancelled ) {
                        setResult( errors );
                        setDismissed( false );
                    }
                } catch ( e ) {
                    if ( ! cancelled ) {
                        setResult( [] );
                        setDismissed( false );
                    }
                }
                if ( ! cancelled ) setScanning( false );
            } )();
            return function() { cancelled = true; };
        }, [ postContent ] );

        // Lock publishing when errors exist and not dismissed.
        useEffect( function() {
            if ( ! publishGateActive || scanning || ! result ) return;

            if ( result.length > 0 && ! dismissed ) {
                editorDispatch.lockPostSaving( 'spellmatic-errors' );
            } else {
                editorDispatch.unlockPostSaving( 'spellmatic-errors' );
            }
        }, [ result, dismissed, scanning, publishGateActive, editorDispatch ] );

        function handleDismiss() {
            setDismissed( true );
            editorDispatch.unlockPostSaving( 'spellmatic-errors' );
        }

        if ( scanning ) {
            return el( PluginPrePublishPanel, { title: 'Spelling Check', icon: 'editor-spellcheck' },
                el( 'div', { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
                    el( Spinner, {} ), 'Checking spelling…'
                )
            );
        }

        if ( ! result ) return null;

        if ( result.length === 0 ) {
            return el( PluginPrePublishPanel, { title: 'Spelling Check', icon: 'editor-spellcheck' },
                el( 'div', { style: { color: '#16a34a', fontWeight: 600 } },
                    '✓ No spelling or grammar errors detected.'
                )
            );
        }

        return el( PluginPrePublishPanel, {
            title: result.length + ' Spelling Error' + ( result.length !== 1 ? 's' : '' ),
            icon: 'warning',
            initialOpen: true,
        },
            el( 'p', { style: { color: '#b91c1c', fontSize: '13px', margin: '0 0 8px' } },
                publishGateActive
                    ? result.length + ' spelling error' + ( result.length !== 1 ? 's' : '' ) + ' found. Fix them before publishing, or dismiss to publish anyway.'
                    : 'This post has ' + result.length + ' potential error' + ( result.length !== 1 ? 's' : '' ) + '. Consider fixing them before publishing.'
            ),
            result.slice( 0, 5 ).map( function( err, i ) {
                return el( 'div', { key: i, style: { fontSize: '12px', padding: '4px 0', borderBottom: '1px solid #f3f4f6' } },
                    el( 'code', { style: { background: '#fecaca', padding: '1px 3px', borderRadius: '3px', textDecoration: 'line-through' } }, err.original ),
                    ' → ',
                    el( 'code', { style: { background: '#bbf7d0', padding: '1px 3px', borderRadius: '3px', fontWeight: 600 } }, err.suggestion )
                );
            } ),
            result.length > 5 ? el( 'p', { style: { fontSize: '11px', color: '#6b7280', marginTop: '6px' } },
                '…and ' + ( result.length - 5 ) + ' more. Open the Spellmatic sidebar for full details.'
            ) : null,
            publishGateActive ? el( 'div', { style: { marginTop: '12px' } },
                el( Button, {
                    variant: 'secondary',
                    onClick: handleDismiss,
                    style: { width: '100%' }
                }, 'Publish Anyway' )
            ) : null
        );
    }

    // ── Register the plugin ──────────────────────────────────────────────────
    registerPlugin( 'spellmatic-editor', {
        render: function() {
            return el( Fragment, {},
                el( SpellmaticSidebar ),
                el( SpellmaticPrePublish )
            );
        },
    } );

} )( window.wp );
