import domReady from "@wordpress/dom-ready";
import { createRoot, useEffect, useMemo, useState } from "@wordpress/element";
import MetaSettingsModal from "../components/MetaSettingsModal";
import { ajaxPostJetMenu, buildControlData, getCfg, normalizeContentTypeValue, prepareNavItemSettingsForSave } from "../components/MetaModalHelpers";
import "../components/dynamic-visibility/api/registry";
import "../components/dynamic-visibility/styles/dynamic-visibility.scss";

/**
 * Editor URL
 */
function buildEditorUrl( { itemId, menuId, contentType } ) {
  const config = getCfg();
  const adminUrl = config.adminUrl || `${ window.location.origin }/wp-admin/`;
  const url = new URL( adminUrl );

  url.searchParams.set( "jet-open-editor", "1" );
  url.searchParams.set( "item", String( itemId ) );
  url.searchParams.set( "menu", String( menuId || 0 ) );
  url.searchParams.set( "content", String( contentType || "default" ) );
  url.searchParams.set( "_nonce", config.editorNonce || "" );

  return url.toString();
}

/**
 * Utilities for nav-menus.php DOM
 */
function getNavMenusMenuId() {
  const menuIdInputById = document.querySelector( "input#menu" );

  if ( menuIdInputById?.value ) {
    return Number( menuIdInputById.value ) || 0;
  }

  const menuIdInputByName = document.querySelector( 'input[name="menu"]' );

  if ( menuIdInputByName?.value ) {
    return Number( menuIdInputByName.value ) || 0;
  }

  const menuSelect = document.querySelector( "select#menu" );

  if ( menuSelect?.value ) {
    return Number( menuSelect.value ) || 0;
  }

  return 0;
}

function getNavMenuItemIdFromElement( menuItemElement ) {
  if ( ! menuItemElement ) {
    return 0;
  }

  const databaseIdInput = menuItemElement.querySelector(
      "input.menu-item-data-db-id"
  );

  if ( databaseIdInput?.value ) {
    return Number( databaseIdInput.value ) || 0;
  }

  const fallbackDatabaseIdInput = menuItemElement.querySelector(
      'input[name^="menu-item-db-id"]'
  );

  if ( fallbackDatabaseIdInput?.value ) {
    return Number( fallbackDatabaseIdInput.value ) || 0;
  }

  return 0;
}

function getNavMenuItemDepth( menuItemElement ) {
  if ( ! menuItemElement ) {
    return 0;
  }

  const match = String( menuItemElement.className ).match(
      /menu-item-depth-(\d+)/
  );

  return match ? Number( match[ 1 ] ) || 0 : 0;
}

function isEnabledValue( raw ) {
  return String( raw ) === "true" || raw === true;
}

function getMenuItemRoot( menuItemId ) {
  return document.querySelector( `#menu-item-${ menuItemId }` );
}

function ensureSettingsWrap( menuItemElement ) {
  if ( ! menuItemElement ) return null;

  let wrap = menuItemElement.querySelector( ".jet-menu-item-settings" );

  if ( ! wrap ) {
    wrap = document.createElement( "span" );
    wrap.className = "jet-menu-item-settings";
    menuItemElement.appendChild( wrap );
  }

  let info = wrap.querySelector( ".jet-menu-item-settings__info" );

  if ( ! info ) {
    info = document.createElement( "span" );
    info.className = "jet-menu-item-settings__info";
    wrap.insertBefore( info, wrap.firstChild );
  }

  return wrap;
}

function updateMegaActivatedLabel( menuItemId, enabled ) {
  const cfg = getCfg();
  const menuItemElement = getMenuItemRoot( menuItemId );

  if ( ! menuItemElement ) return;

  const wrap = ensureSettingsWrap( menuItemElement );
  if ( ! wrap ) return;

  const info = wrap.querySelector( ".jet-menu-item-settings__info" );
  if ( ! info ) return;

  info.querySelectorAll( ".mega-enabled" ).forEach( ( n ) => n.remove() );

  if ( ! enabled ) return;

  const label = document.createElement( "span" );
  label.className = "jet-menu-item-settings__info-label mega-enabled";
  label.innerHTML = cfg?.labels?.itemMegaEnableLabel || "Mega Activated";

  info.appendChild( label );
}

/**
 * Inject "Settings" triggers into nav menu items
 */
function injectReactTriggers() {
  const menuItemsContainer = document.querySelector( "#menu-to-edit" );

  if ( ! menuItemsContainer ) {
    return;
  }

  const currentMenuId = getNavMenusMenuId();
  const menuItemElements = menuItemsContainer.querySelectorAll( ".menu-item" );

  menuItemElements.forEach( ( menuItemElement ) => {
    const menuItemId = getNavMenuItemIdFromElement( menuItemElement );

    if ( ! menuItemId ) {
      return;
    }

    if ( menuItemElement.querySelector( "[data-jet-menu-item-settings]" ) ) {
      return;
    }

    const itemDepth = getNavMenuItemDepth( menuItemElement );

    const wrap = ensureSettingsWrap( menuItemElement );

    if ( ! wrap ) {
      return;
    }

    const cfg = getCfg();
    const enabled = String( cfg?.itemsSettings?.[ menuItemId ]?.enabled || "" ) === "true";

    updateMegaActivatedLabel( menuItemId, enabled );

    const triggerElement = document.createElement( "span" );
    triggerElement.className = "jet-menu-item-settings__trigger--modal";

    // Icon
    const icon = document.createElement( "span" );
    icon.className = "dashicons dashicons-admin-generic";
    icon.setAttribute( "aria-hidden", "true" );
    triggerElement.appendChild( icon );

    // Text
    const text = document.createElement( "span" );
    text.className = "jet-menu-item-settings__trigger-text";
    text.textContent = "Settings";
    triggerElement.appendChild( text );

    triggerElement.setAttribute( "data-jet-menu-item-settings", "" );
    triggerElement.setAttribute( "data-menu-item-id", String( menuItemId ) );
    triggerElement.setAttribute( "data-menu-id", String( currentMenuId || 0 ) );
    triggerElement.setAttribute( "data-item-depth", String( itemDepth ) );
    triggerElement.setAttribute( "role", "button" );
    triggerElement.setAttribute( "tabindex", "0" );

    triggerElement.addEventListener( "keydown", ( event ) => {

      if ( event.key === "Enter" || event.key === " " ) {
        event.preventDefault();
        triggerElement.click();
      }

    } );

    wrap.appendChild( triggerElement );
  } );
}

function observeNavMenusChanges() {
  const menuItemsContainer = document.querySelector( "#menu-to-edit" );

  if ( ! menuItemsContainer ) {
    return;
  }

  let injectDebounceTimer = null;

  const scheduleInject = () => {

    if ( injectDebounceTimer ) {
      window.clearTimeout( injectDebounceTimer );
    }

    injectDebounceTimer = window.setTimeout( injectReactTriggers, 150 );
  };

  injectReactTriggers();

  const mutationObserver = new MutationObserver( scheduleInject );

  mutationObserver.observe( menuItemsContainer, {
    childList: true,
    subtree: true,
  } );

  const menuSelect = document.querySelector( "select#menu" );

  if ( menuSelect ) {
    menuSelect.addEventListener( "change", scheduleInject );
  }
}

/**
 * Modal host
 */
function MetaModalHost() {
  const [ isOpen, setIsOpen ] = useState( false );
  const [ menuId, setMenuId ] = useState( 0 );
  const [ itemId, setItemId ] = useState( 0 );
  const [ itemDepth, setItemDepth ] = useState( 0 );

  const [ isLoading, setIsLoading ] = useState( false );
  const [ isSaving, setIsSaving ] = useState( false );
  const [ controlData, setControlData ] = useState( null );

  const editorUrl = useMemo( () => {

    if ( ! isOpen || ! itemId ) {
      return "";
    }

    const contentType = normalizeContentTypeValue(
        controlData?.content_type?.value || "default"
    );

    return buildEditorUrl( {
      itemId,
      menuId,
      contentType,
    } );

  }, [ isOpen, itemId, menuId, controlData?.content_type?.value ] );

  const setControlValue = ( key, value ) => {
    setControlData( ( previous ) => ( {
      ...( previous || {} ),
      [ key ]: { ...( previous?.[ key ] || {} ), value },
    } ) );
  };

  const closeModal = () => {
    setIsOpen( false );
    setMenuId( 0 );
    setItemId( 0 );
    setItemDepth( 0 );
    setControlData( null );
    setIsLoading( false );
    setIsSaving( false );
  };

  const loadItemSettings = async ( menuItemId, depth ) => {
    setIsLoading( true );

    try {
      const response = await ajaxPostJetMenu( {
        action: "jet_get_nav_item_settings",
        data: {
          itemId: menuItemId,
          itemDepth: depth,
        },
      } );

      if ( response?.success && response?.data?.settings ) {
        setControlData( buildControlData( response.data.settings ) );
      } else {
        setControlData( buildControlData( {} ) );
      }
    } finally {
      setIsLoading( false );
    }
  };

  const openForItem = async ( { itemId, menuId, itemDepth } ) => {

    if ( ! itemId ) {
      return;
    }

    setItemId( Number( itemId ) );
    setMenuId( Number( menuId || 0 ) );
    setItemDepth( Number( itemDepth || 0 ) );
    setIsOpen( true );

    await loadItemSettings( Number( itemId ), Number( itemDepth || 0 ) );
  };

  useEffect( () => {
    window.JetMenuMetaModal = window.JetMenuMetaModal || {};
    window.JetMenuMetaModal.open = openForItem;
    window.JetMenuMetaModal.close = closeModal;

    return () => {
      delete window.JetMenuMetaModal?.open;
      delete window.JetMenuMetaModal?.close;
    };
  }, [] );

  const onSave = async () => {

    if ( ! itemId || ! controlData ) {
      return;
    }

    setIsSaving( true );

    try {
      const itemSettings = prepareNavItemSettingsForSave( controlData );

      const response = await ajaxPostJetMenu( {
        action: "jet_save_nav_item_settings",
        data: {
          itemId,
          itemDepth,
          itemSettings,
        },
      } );

      if ( ! response?.success ) {
        alert( response?.data?.message || "Failed to save item settings" );
        return;
      }

      const enabledNow = isEnabledValue( controlData?.enabled?.value );

      updateMegaActivatedLabel( itemId, enabledNow );

      window.JetMenuMetaModalConfig = window.JetMenuMetaModalConfig || {};
      window.JetMenuMetaModalConfig.itemsSettings = window.JetMenuMetaModalConfig.itemsSettings || {};
      window.JetMenuMetaModalConfig.itemsSettings[ itemId ] = window.JetMenuMetaModalConfig.itemsSettings[ itemId ] || {};
      window.JetMenuMetaModalConfig.itemsSettings[ itemId ].enabled = enabledNow ? "true" : "false";

      await loadItemSettings( itemId, itemDepth );

    } finally {
      setIsSaving( false );
    }
  };

  const onOpenEditorInNewTab = () => {

    if ( editorUrl ) {
      window.open( editorUrl, "_blank", "noopener,noreferrer" );
    }

  };

  return (
      <MetaSettingsModal
          isOpen={ isOpen }
          onClose={ closeModal }
          loading={ isLoading }
          saving={ isSaving }
          editorUrl={ editorUrl }
          onOpenEditorInNewTab={ onOpenEditorInNewTab }
          controlData={ controlData }
          setControlValue={ setControlValue }
          onSave={ onSave }
      />
  );
}

/**
 * Boot
 */
domReady( () => {
  const rootElement = document.createElement( "div" );
  rootElement.id = "jet-menu-meta-modal-root";
  document.body.appendChild( rootElement );

  createRoot( rootElement ).render( <MetaModalHost /> );

  observeNavMenusChanges();

  document.addEventListener( "click", ( event ) => {

    const triggerElement = event.target?.closest?.(
        "[data-jet-menu-item-settings]"
    );

    if ( ! triggerElement ) {
      return;
    }

    const menuItemId = Number( triggerElement.getAttribute( "data-menu-item-id" ) || 0 );
    const menuId     = Number( triggerElement.getAttribute( "data-menu-id" ) || 0 );
    const itemDepth  = Number( triggerElement.getAttribute( "data-item-depth" ) || 0 );

    if ( ! menuItemId ) {
      return;
    }

    event.preventDefault();
    event.stopPropagation();

    window.JetMenuMetaModal?.open?.( {
      itemId: menuItemId,
      menuId,
      itemDepth,
    } );

  } );
} );
