(function() {
    'use strict';

    const { registerBlockType } = wp.blocks;
    const {
        SelectControl,
        PanelBody,
        ToggleControl,
        Button,
        Spinner,
        Notice,
        ExternalLink,
    } = wp.components;
    const { InspectorControls, useBlockProps } = wp.blockEditor;
    const ServerSideRender = wp.serverSideRender;
    const {
        Fragment,
        createElement: el,
        useState,
        useEffect,
        useMemo,
        useRef,
        useCallback,
    } = wp.element;
    const { __, sprintf } = wp.i18n;
    const { apiFetch } = wp;

    const INHERIT_VALUE = '__inherit__';

    const normalizeToggleToAttribute = ( isEnabled ) => ( isEnabled ? 'yes' : 'no' );

    const resolveToggleFromAttribute = ( value, fallback ) => {
        if ( value === undefined || value === '' ) {
            return fallback;
        }

        return value === 'yes';
    };

    const findLabel = ( options, value ) => {
        if ( ! Array.isArray( options ) || ! value ) {
            return '';
        }

        const match = options.find( ( item ) => item && item.value === value );
        return match ? match.label : '';
    };

    const buildShortcodeString = ( shortcodeType, readingSlug, overrides ) => {
        if ( ! readingSlug ) {
            return '';
        }

        const shortcodeMap = {
            daily: 'card-oracle-daily',
            random: 'card-oracle-random',
            reading: 'card-oracle',
        };

        const shortcodeName = shortcodeMap[ shortcodeType ] || 'card-oracle-daily';
        let shortcode = '[' + shortcodeName + ' name="' + readingSlug + '"]';

        if ( shortcodeName === 'card-oracle' ) {
            const parts = [];

            if ( overrides.deckLayout ) {
                parts.push( 'deck_layout="' + overrides.deckLayout + '"' );
            }

            if ( overrides.presentationLayout ) {
                parts.push( 'presentation="' + overrides.presentationLayout + '"' );
            }

            if ( overrides.showLayoutTable ) {
                parts.push( 'show_layout_table="' + overrides.showLayoutTable + '"' );
            }

            if ( overrides.displayQuestionInput ) {
                parts.push( 'display_question="' + overrides.displayQuestionInput + '"' );
            }

            if ( overrides.questionLayout ) {
                parts.push( 'question_layout="' + overrides.questionLayout + '"' );
            }

            if ( parts.length ) {
                shortcode = '[' + shortcodeName + ' name="' + readingSlug + '" ' + parts.join( ' ' ) + ']';
            }
        }

        return shortcode;
    };

    const DOCS_BASE_URL = 'https://chillichalli.com/card-oracle/docs/shortcodes';

    registerBlockType( 'card-oracle/shortcode-block', {
        title: __( 'Card Oracle Reading', 'card-oracle' ),
        icon: 'palmtree',
        category: 'widgets',
        description: __( 'Add a Card Oracle reading shortcode with easy reading selection.', 'card-oracle' ),

        attributes: {
            readingId: { type: 'string', default: '' },
            readingName: { type: 'string', default: '' },
            shortcodeType: { type: 'string', default: 'daily' },
            deckLayout: { type: 'string', default: '' },
            presentationLayout: { type: 'string', default: '' },
            showLayoutTable: { type: 'string', default: '' },
            displayQuestionInput: { type: 'string', default: '' },
            questionLayout: { type: 'string', default: '' },
        },

        edit: function( props ) {
            const { attributes, setAttributes } = props;
            const {
                readingId,
                readingName,
                shortcodeType,
                deckLayout,
                presentationLayout,
                showLayoutTable,
                displayQuestionInput,
                questionLayout,
            } = attributes;

            const [ readings, setReadings ] = useState( [] );
            const [ options, setOptions ] = useState( { deckLayouts: [], questionLayouts: [] } );
            const [ loading, setLoading ] = useState( true );
            const [ error, setError ] = useState( null );
            const [ copyState, setCopyState ] = useState( 'idle' );
            const previousReadingRef = useRef( readingName );

            useEffect( () => {
                if ( copyState === 'idle' ) {
                    return undefined;
                }

                const timeout = setTimeout( () => setCopyState( 'idle' ), 2000 );
                return () => clearTimeout( timeout );
            }, [ copyState ] );

            useEffect( () => {
                const controller = new AbortController();

                apiFetch( { path: '/card-oracle/v1/readings', signal: controller.signal } )
                    .then( ( payload ) => {
                        if ( payload && Array.isArray( payload.readings ) ) {
                            setReadings( payload.readings );
                            setOptions( {
                                deckLayouts: Array.isArray( payload.options && payload.options.deckLayouts ) ? payload.options.deckLayouts : [],
                                questionLayouts: Array.isArray( payload.options && payload.options.questionLayouts ) ? payload.options.questionLayouts : [],
                            } );
                            setError( null );
                        } else {
                            setError( __( 'Invalid data received from server.', 'card-oracle' ) );
                        }
                        setLoading( false );
                    } )
                    .catch( ( fetchError ) => {
                        if ( fetchError && fetchError.name === 'AbortError' ) {
                            return;
                        }

                        setError( __( 'Failed to load readings. Please try again.', 'card-oracle' ) );
                        setLoading( false );
                    } );

                return () => controller.abort();
            }, [] );

           useEffect( () => {
               if ( ! readingName ) {
                   previousReadingRef.current = readingName;
                   return;
               }

               if ( previousReadingRef.current === readingName ) {
                   return;
               }

               const selected = readings.find( ( item ) => item.slug === readingName );
               if ( selected ) {
                   setAttributes( {
                       readingId: String( selected.id || '' ),
                       deckLayout: '',
                       presentationLayout: '',
                       showLayoutTable: '',
                       displayQuestionInput: '',
                       questionLayout: '',
                   } );
               }

               previousReadingRef.current = readingName;
           }, [ readingName, readings ] );

            useEffect( () => {
                if ( ! readingName || readingId ) {
                    return;
                }

                const target = readings.find( ( item ) => item.slug === readingName );
                if ( target ) {
                    setAttributes( { readingId: String( target.id || '' ) } );
                }
            }, [ readingName, readingId, readings, setAttributes ] );

            const blockProps = useBlockProps( { className: 'card-oracle-block' } );
            const isReadingType = shortcodeType === 'reading';

            const readingOptions = useMemo( () => {
                const base = [ { label: __( 'Select a Reading...', 'card-oracle' ), value: '' } ];
                const mapped = readings.map( ( reading ) => ( {
                    label: reading.title,
                    value: reading.slug,
                } ) );
                return base.concat( mapped );
            }, [ readings ] );

            const selectedReading = useMemo( () => readings.find( ( item ) => item.slug === readingName ), [ readings, readingName ] );

            const deckDefaultLabel = findLabel( options.deckLayouts, selectedReading ? selectedReading.deckLayout : '' ) || __( 'Standard', 'card-oracle' );
            const deckInheritLabel = sprintf( __( 'Use reading default (%s)', 'card-oracle' ), deckDefaultLabel );
            const deckLayoutOptions = useMemo( () => {
                return [
                    { label: deckInheritLabel, value: INHERIT_VALUE },
                    ...options.deckLayouts,
                ];
            }, [ deckInheritLabel, options.deckLayouts ] );

            const presentationBaseLabel = findLabel( selectedReading ? selectedReading.presentationOptions : [], selectedReading ? selectedReading.presentationLayout : '' ) || __( 'Standard', 'card-oracle' );
            const presentationInheritLabel = sprintf( __( 'Use reading default (%s)', 'card-oracle' ), presentationBaseLabel );
            const presentationOptions = useMemo( () => {
                const available = Array.isArray( selectedReading && selectedReading.presentationOptions ) ? selectedReading.presentationOptions : [];
                return [ { label: presentationInheritLabel, value: INHERIT_VALUE } ].concat( available );
            }, [ selectedReading, presentationInheritLabel ] );

            const questionDefaultLabel = findLabel( options.questionLayouts, selectedReading ? selectedReading.questionLayout : '' );
            const questionInheritLabel = questionDefaultLabel ? sprintf( __( 'Use reading default (%s)', 'card-oracle' ), questionDefaultLabel ) : __( 'Use reading default', 'card-oracle' );
            const questionLayoutOptions = useMemo( () => {
                return [
                    { label: questionInheritLabel, value: INHERIT_VALUE },
                    ...options.questionLayouts,
                ];
            }, [ questionInheritLabel, options.questionLayouts ] );

            const layoutTableValue = resolveToggleFromAttribute( showLayoutTable, !! ( selectedReading && selectedReading.showLayoutTable ) );
            const layoutTableInherited = showLayoutTable === '';
            const questionInputValue = resolveToggleFromAttribute( displayQuestionInput, !! ( selectedReading && selectedReading.displayQuestionInput ) );
            const questionInputInherited = displayQuestionInput === '';
            const docsLink = useCallback( ( anchor, text ) => {
                const href = anchor ? DOCS_BASE_URL + anchor : DOCS_BASE_URL;
                return el( ExternalLink, { href }, text || __( 'Learn more', 'card-oracle' ) );
            }, [] );

            const controlsDisabled = ! selectedReading || ! isReadingType;

            const shortcodePreview = buildShortcodeString( shortcodeType, readingName, {
                deckLayout,
                presentationLayout,
                showLayoutTable,
                displayQuestionInput,
                questionLayout,
            } );

            const handleCopyShortcode = useCallback( () => {
                if ( ! shortcodePreview ) {
                    return;
                }

                const fallbackCopy = () => {
                    const tempInput = document.createElement( 'textarea' );
                    tempInput.value = shortcodePreview;
                    tempInput.setAttribute( 'readonly', '' );
                    tempInput.style.position = 'absolute';
                    tempInput.style.left = '-9999px';
                    document.body.appendChild( tempInput );
                    tempInput.select();

                    try {
                        const successful = document.execCommand( 'copy' );
                        setCopyState( successful ? 'success' : 'error' );
                    } catch ( copyError ) {
                        setCopyState( 'error' );
                    }

                    document.body.removeChild( tempInput );
                };

                if ( navigator.clipboard && window.isSecureContext ) {
                    navigator.clipboard.writeText( shortcodePreview )
                        .then( () => setCopyState( 'success' ) )
                        .catch( fallbackCopy );
                    return;
                }

                fallbackCopy();
            }, [ shortcodePreview ] );

            const inspector = el(
                InspectorControls,
                {},
                el(
                    PanelBody,
                    { title: __( 'Reading Defaults', 'card-oracle' ), initialOpen: false },
                    el( 'p', { className: 'card-oracle-block__panel-description' },
                        __( 'The values configured on the reading itself. Overrides in the panels below take precedence; otherwise these defaults apply.', 'card-oracle' )
                    ),
                    selectedReading ?
                        el( 'ul', { className: 'card-oracle-block__reading-defaults' },
                            el( 'li', {},
                                el( 'strong', {}, __( 'Deck layout:', 'card-oracle' ) ),
                                ' ', deckDefaultLabel
                            ),
                            el( 'li', {},
                                el( 'strong', {}, __( 'Presentation layout:', 'card-oracle' ) ),
                                ' ', presentationBaseLabel
                            ),
                            el( 'li', {},
                                el( 'strong', {}, __( 'Question layout:', 'card-oracle' ) ),
                                ' ', questionDefaultLabel || __( 'Follow reading default', 'card-oracle' )
                            ),
                            el( 'li', {},
                                el( 'strong', {}, __( 'Show layout table:', 'card-oracle' ) ),
                                ' ', ( selectedReading && selectedReading.showLayoutTable ) ? __( 'Yes', 'card-oracle' ) : __( 'No', 'card-oracle' )
                            ),
                            el( 'li', {},
                                el( 'strong', {}, __( 'Display question input:', 'card-oracle' ) ),
                                ' ', ( selectedReading && selectedReading.displayQuestionInput ) ? __( 'Yes', 'card-oracle' ) : __( 'No', 'card-oracle' )
                            )
                        ) :
                        el( 'p', { className: 'card-oracle-block__reading-defaults--empty' }, __( 'Select a reading to view its saved defaults.', 'card-oracle' ) )
                ),
                el(
                    PanelBody,
                    { title: __( 'Reading Settings', 'card-oracle' ), initialOpen: true },
                    el( SelectControl, {
                        label: __( 'Shortcode Type', 'card-oracle' ),
                        value: shortcodeType,
                        options: [
                            { label: __( 'Daily Card', 'card-oracle' ), value: 'daily' },
                            { label: __( 'Random Card', 'card-oracle' ), value: 'random' },
                            { label: __( 'Full Reading', 'card-oracle' ), value: 'reading' },
                        ],
                        onChange: ( value ) => setAttributes( { shortcodeType: value } ),
                        help: el( Fragment, {},
                            __( 'Daily and Random render one card; Full Reading shows the entire spread.', 'card-oracle' ),
                            ' ', docsLink( '#shortcode-types' )
                        ),
                    } ),
                   el( SelectControl, {
                        label: __( 'Select Reading', 'card-oracle' ),
                        value: readingName,
                        options: readingOptions,
                        onChange: ( value ) => {
                            const target = readings.find( ( item ) => item.slug === value );
                            const updates = { readingName: value };
                            if ( target ) {
                                updates.readingId = String( target.id || '' );
                            }
                            setAttributes( updates );
                        },
                        disabled: loading,
                        help: __( 'Choose any published reading. The preview updates immediately.', 'card-oracle' ),
                    } ),
                    loading && el( 'p', { className: 'card-oracle-block__loading-hint' }, __( 'Loading readings...', 'card-oracle' ) ),
                    error && el( Notice, { status: 'error', isDismissible: false }, error )
                ),
                el(
                    PanelBody,
                    { title: __( 'Layout Options', 'card-oracle' ), initialOpen: true },
                    ! isReadingType && el( Notice, { status: 'info', isDismissible: false }, __( 'Switch to the full reading shortcode to configure layout overrides.', 'card-oracle' ) ),
                    isReadingType && el( SelectControl, {
                        label: __( 'Deck Layout', 'card-oracle' ),
                        value: deckLayout ? deckLayout : INHERIT_VALUE,
                        options: deckLayoutOptions,
                        onChange: ( value ) => {
                            setAttributes( { deckLayout: value === INHERIT_VALUE ? '' : value } );
                        },
                        disabled: controlsDisabled,
                        help: el( Fragment, {},
                            __( 'Pick a different deck arrangement for this embed.', 'card-oracle' ),
                            ' ', docsLink( '#layout-overrides' )
                        ),
                    } ),
                    isReadingType && el( SelectControl, {
                        label: __( 'Presentation Layout', 'card-oracle' ),
                        value: presentationLayout ? presentationLayout : INHERIT_VALUE,
                        options: presentationOptions,
                        onChange: ( value ) => {
                            setAttributes( { presentationLayout: value === INHERIT_VALUE ? '' : value } );
                        },
                        disabled: controlsDisabled,
                        help: el( Fragment, {},
                            __( 'Override the spread markup shown to visitors.', 'card-oracle' ),
                            ' ', docsLink( '#presentation-layouts' )
                        ),
                    } )
                ),
                el(
                    PanelBody,
                    { title: __( 'Display Toggles', 'card-oracle' ), initialOpen: false },
                    ! isReadingType && el( Notice, { status: 'info', isDismissible: false }, __( 'Display settings are available for the full reading shortcode.', 'card-oracle' ) ),
                    isReadingType && el( ToggleControl, {
                        label: __( 'Show Layout Table', 'card-oracle' ),
                        checked: layoutTableValue,
                        onChange: ( value ) => {
                            setAttributes( { showLayoutTable: normalizeToggleToAttribute( value ) } );
                        },
                        help: el( Fragment, {},
                            layoutTableInherited ? __( 'Using reading default', 'card-oracle' ) : __( 'Override applied', 'card-oracle' ),
                            ' ', docsLink( '#layout-table' )
                        ),
                        disabled: controlsDisabled,
                    } ),
                    isReadingType && el( Button, {
                        variant: 'link',
                        disabled: controlsDisabled || layoutTableInherited,
                        onClick: () => setAttributes( { showLayoutTable: '' } ),
                    }, __( 'Reset to default', 'card-oracle' ) ),
                    isReadingType && el( ToggleControl, {
                        label: __( 'Display Question Input', 'card-oracle' ),
                        checked: questionInputValue,
                        onChange: ( value ) => {
                            setAttributes( { displayQuestionInput: normalizeToggleToAttribute( value ) } );
                        },
                        help: el( Fragment, {},
                            questionInputInherited ? __( 'Using reading default', 'card-oracle' ) : __( 'Override applied', 'card-oracle' ),
                            ' ', docsLink( '#question-form' )
                        ),
                        disabled: controlsDisabled,
                    } ),
                    isReadingType && el( Button, {
                        variant: 'link',
                        disabled: controlsDisabled || questionInputInherited,
                        onClick: () => setAttributes( { displayQuestionInput: '' } ),
                    }, __( 'Reset to default', 'card-oracle' ) ),
                    isReadingType && el( SelectControl, {
                        label: __( 'Question Layout', 'card-oracle' ),
                        value: questionLayout ? questionLayout : INHERIT_VALUE,
                        options: questionLayoutOptions,
                        onChange: ( value ) => {
                            setAttributes( { questionLayout: value === INHERIT_VALUE ? '' : value } );
                        },
                        disabled: controlsDisabled,
                        help: el( Fragment, {},
                            __( 'Set an alternate question intake layout.', 'card-oracle' ),
                            ' ', docsLink( '#question-layouts' )
                        ),
                    } )
                ),
                el(
                    PanelBody,
                    { title: __( 'Help & Docs', 'card-oracle' ), initialOpen: false },
                    el( 'p', {}, __( 'Need more examples? Explore the shortcode reference for advanced usage.', 'card-oracle' ) ),
                    el( ExternalLink, {
                        href: 'https://chillichalli.com/card-oracle/docs/shortcodes',
                    }, __( 'Open shortcode documentation', 'card-oracle' ) )
                )
            );

            const previewClasses = [ 'card-oracle-block-preview' ];
            if ( readingName ) {
                previewClasses.push( 'has-reading' );
            }
            if ( loading ) {
                previewClasses.push( 'is-loading' );
            }
            if ( error ) {
                previewClasses.push( 'has-error' );
            }
            if ( isReadingType ) {
                previewClasses.push( 'is-reading-type' );
            }

            const overrides = {
                deckLayout: deckLayout,
                presentationLayout: presentationLayout,
                showLayoutTable: showLayoutTable,
                displayQuestionInput: displayQuestionInput,
                questionLayout: questionLayout,
            };

            const previewAttributes = {
                readingId: readingId,
                readingName: readingName,
                shortcodeType: shortcodeType,
                deckLayout: deckLayout,
                presentationLayout: presentationLayout,
                showLayoutTable: showLayoutTable,
                displayQuestionInput: displayQuestionInput,
                questionLayout: questionLayout,
            };

            let previewContent;

            if ( loading ) {
                previewContent = el(
                    'div',
                    { className: 'card-oracle-block-preview__state' },
                    el( Spinner, {} ),
                    el( 'p', {}, __( 'Loading readings…', 'card-oracle' ) )
                );
            } else if ( error ) {
                previewContent = el( Notice, { status: 'error', isDismissible: false }, error );
            } else if ( ! readingName ) {
                previewContent = el(
                    'div',
                    { className: 'card-oracle-block-preview__state' },
                    el( 'h4', {}, __( 'Card Oracle Reading', 'card-oracle' ) ),
                    el( 'p', {}, __( 'Select a reading from the sidebar to preview it here.', 'card-oracle' ) )
                );
            } else {
                previewContent = el( Fragment, {},
                    el( ServerSideRender, {
                        block: 'card-oracle/shortcode-block',
                        attributes: previewAttributes,
                        LoadingResponsePlaceholder: () => el( 'div', { className: 'card-oracle-block-preview__state' }, el( Spinner, {} ), el( 'p', {}, __( 'Rendering preview…', 'card-oracle' ) ) ),
                        ErrorResponsePlaceholder: ( response ) => el( Notice, { status: 'error', isDismissible: false }, response && response.message ? response.message : __( 'Unable to render preview.', 'card-oracle' ) ),
                    } ),
                    el( 'div', { className: 'card-oracle-block-preview__meta' },
                        el( 'code', {}, shortcodePreview ),
                        el( 'div', { className: 'card-oracle-block-preview__actions' },
                            el( Button, {
                                variant: 'secondary',
                                onClick: handleCopyShortcode,
                                disabled: ! shortcodePreview,
                            }, copyState === 'success' ? __( 'Copied!', 'card-oracle' ) : __( 'Copy shortcode', 'card-oracle' ) ),
                            copyState !== 'idle' && el( 'span', { className: 'card-oracle-block-preview__feedback is-' + copyState, 'aria-live': 'polite' }, copyState === 'success' ? __( 'Shortcode copied to clipboard.', 'card-oracle' ) : __( 'Unable to copy shortcode.', 'card-oracle' ) )
                        ),
                        el( 'p', {}, sprintf( __( 'Type: %s', 'card-oracle' ), (
                            shortcodeType === 'daily' ? __( 'Daily Card', 'card-oracle' ) :
                            shortcodeType === 'random' ? __( 'Random Card', 'card-oracle' ) :
                            __( 'Full Reading', 'card-oracle' )
                        ) ) )
                    )
                );
            }

            return el(
                Fragment,
                {},
                inspector,
                el(
                    'div',
                    blockProps,
                    el( 'div', { className: previewClasses.join( ' ' ) }, previewContent )
                )
            );
        },

        save: function() {
            return null;
        },
    } );
})();
