import { slideToggle } from '@site/js/utils/dom.js';

/**
 * Mobile flyout menu (vanilla front-end copy).
 *
 * Sets up the off-canvas mobile menu:
 *   - Clones parent links into the top of each submenu (so users can tap
 *     the parent without losing access to its landing page).
 *   - Tags each parent link with `.js_mobileSubmenu`; a single delegated
 *     click handler toggles the open state and slides the submenu.
 *   - Wires `.flyoutButton` to toggle `body.flyoutActive`, preserving the
 *     scroll position when `is_fixed` is true.
 *   - Init / destroy based on `window.breakpoints.flyout`, re-evaluated on
 *     `resize` and `orientationchange`.
 *
 * Front-end only. The admin's legacy copy is left untouched until the
 * later admin spec.
 */

const DEFAULTS = {
    flyout_wrapper: '.flyoutWrap',
    clone: true,
    submenu_selector: '> ul',
    is_fixed: true,
    position: 'right', // 'left' | 'right' | 'top'
    move_site: true,
};

export default class MobileMenu {

    constructor(options = {}) {
        this.settings = { ...DEFAULTS, ...options };
        this.flyoutWrapper = document.querySelector(this.settings.flyout_wrapper);

        if (!this.flyoutWrapper) {
            console.error(`MobileMenu: no element found for '${this.settings.flyout_wrapper}'.`);
            return;
        }

        this.flyoutWrapper._mobileMenuInstance = this;

        if (this.settings.move_site) {
            document.body.classList.add('flyoutMove');
        }

        switch (this.settings.position) {
            case 'left':
                document.body.classList.add('flyoutLeft');
                break;
            case 'top':
                document.body.classList.add('flyoutTop');
                break;
            default:
                document.body.classList.add('flyoutRight');
                break;
        }

        if (this.settings.is_fixed) {
            document.body.classList.add('fixedFlyout');
        }

        this.bind();
        this.onResize();

        this._onResize = () => this.onResize();
        window.addEventListener('resize', this._onResize);
        window.addEventListener('orientationchange', this._onResize);
    }

    bind() {
        // Delegated click for every submenu trigger added by `init()`.
        this._onSubmenuClick = (event) => {
            const trigger = event.target instanceof Element
                ? event.target.closest('.js_mobileSubmenu')
                : null;
            if (!trigger) {
                return;
            }
            event.preventDefault();

            const parentLi = trigger.closest('li');
            if (!parentLi) {
                return;
            }
            const submenu = parentLi.querySelector(`:scope ${this.settings.submenu_selector}`);
            if (!submenu) {
                return;
            }

            // Close any sibling that's currently open.
            if (!parentLi.classList.contains('open')) {
                const parent = parentLi.parentElement;
                parent?.querySelectorAll(':scope > li.open').forEach((sibling) => {
                    if (sibling === parentLi) {
                        return;
                    }
                    sibling.classList.remove('open');
                    const siblingSubmenu = sibling.querySelector(`:scope ${this.settings.submenu_selector}`);
                    if (siblingSubmenu && siblingSubmenu.offsetHeight > 0) {
                        slideToggle(siblingSubmenu, 500);
                    }
                });
            }

            parentLi.classList.toggle('open');
            slideToggle(submenu, 500);
        };
        document.body.addEventListener('click', this._onSubmenuClick);

        // Flyout open / close button.
        this._onFlyoutButtonClick = (event) => {
            const button = event.target instanceof Element
                ? event.target.closest('.flyoutButton')
                : null;
            if (!button) {
                return;
            }
            event.preventDefault();

            const flyout = document.querySelector(this.settings.flyout_wrapper);
            flyout?.classList.add('firstClick');

            if (document.body.classList.contains('fixedFlyout')) {
                if (document.body.classList.contains('flyoutActive')) {
                    document.body.classList.remove('flyoutActive');
                    const stored = parseInt(document.body.dataset.storedScroll || '0', 10);
                    window.scrollTo({ top: stored });
                    window.setTimeout(() => {
                        flyout?.querySelector('.isClickable.open')?.click();
                    }, 1000);
                } else {
                    document.body.dataset.storedScroll = String(window.scrollY);
                    document.body.classList.add('flyoutActive');
                }
            } else {
                document.body.classList.toggle('flyoutActive');
            }
        };
        document.addEventListener('click', this._onFlyoutButtonClick);
    }

    init() {
        const wrapper = this.flyoutWrapper;
        if (!wrapper) {
            return;
        }
        document.body.classList.add('flyoutInitialised');

        wrapper.querySelectorAll('.mainMenu li').forEach((li) => {
            const submenu = li.querySelector(`:scope ${this.settings.submenu_selector}`);
            if (!submenu) {
                return;
            }
            const parentLink = li.querySelector(':scope > a');
            if (!parentLink) {
                return;
            }

            if (this.settings.clone && !submenu.querySelector(':scope > li > .clone')) {
                const duplicate = parentLink.cloneNode(true);
                duplicate.classList.add('clone');
                const wrapLi = document.createElement('li');
                wrapLi.appendChild(duplicate);
                submenu.insertBefore(wrapLi, submenu.firstChild);
            }

            parentLink.classList.add('js_mobileSubmenu');
        });
    }

    destroy() {
        const wrapper = this.flyoutWrapper;
        if (!wrapper) {
            return;
        }

        wrapper.querySelectorAll('.js_mobileSubmenu').forEach((el) => {
            el.classList.remove('js_mobileSubmenu');
        });

        wrapper.querySelectorAll('.mainMenu li').forEach((li) => {
            const submenu = li.querySelector(`:scope ${this.settings.submenu_selector}`);
            submenu?.removeAttribute('style');
        });

        wrapper.querySelectorAll('.clone').forEach((clone) => {
            clone.parentElement?.remove();
        });

        document.body.classList.remove('flyoutActive', 'flyoutInitialised');
    }

    kill() {
        this.destroy();
        document.body.classList.remove('fixedFlyout', 'flyoutLeft', 'flyoutRight', 'flyoutTop', 'flyoutMove');
        if (this._onSubmenuClick) {
            document.body.removeEventListener('click', this._onSubmenuClick);
        }
        if (this._onFlyoutButtonClick) {
            document.removeEventListener('click', this._onFlyoutButtonClick);
        }
        if (this._onResize) {
            window.removeEventListener('resize', this._onResize);
            window.removeEventListener('orientationchange', this._onResize);
        }
        delete this.flyoutWrapper?._mobileMenuInstance;
    }

    onResize() {
        const flyoutBreakpoint = window.breakpoints?.flyout ?? 1120;
        const aboveBreakpoint = window.matchesMediaQuery(flyoutBreakpoint);
        const belowBreakpoint = window.matchesMediaQuery(0, flyoutBreakpoint);

        if (aboveBreakpoint && document.body.classList.contains('flyoutInitialised')) {
            this.destroy();
        } else if (belowBreakpoint && !document.body.classList.contains('flyoutInitialised')) {
            this.init();
        }
    }
}

// Legacy global — `sites/default/js/script.js` still calls this by name
// during its own ready handler. Drop this alias once script.js is
// converted in a later Phase 3 batch.
window.mtcMobileMenu = function mtcMobileMenu(options) {
    return new MobileMenu(options);
};
