(() => {
  const SCRIPT_ID = 'excalidraw-control-script';
  if (window[SCRIPT_ID]) {
    return;
  }
  function getExcalidrawAPIFromDOM(domElement) {
    if (!domElement) {
      return null;
    }
    const reactFiberKey = Object.keys(domElement).find(
      (key) => key.startsWith('__reactFiber$') || key.startsWith('__reactInternalInstance$'),
    );
    if (!reactFiberKey) {
      return null;
    }
    let fiberNode = domElement[reactFiberKey];
    if (!fiberNode) {
      return null;
    }
    function isExcalidrawAPI(obj) {
      return (
        typeof obj === 'object' &&
        obj !== null &&
        typeof obj.updateScene === 'function' &&
        typeof obj.getSceneElements === 'function' &&
        typeof obj.getAppState === 'function'
      );
    }
    function findApiInObject(objToSearch) {
      if (isExcalidrawAPI(objToSearch)) {
        return objToSearch;
      }
      if (typeof objToSearch === 'object' && objToSearch !== null) {
        for (const key in objToSearch) {
          if (Object.prototype.hasOwnProperty.call(objToSearch, key)) {
            const found = findApiInObject(objToSearch[key]);
            if (found) {
              return found;
            }
          }
        }
      }
      return null;
    }
    let excalidrawApiInstance = null;
    let attempts = 0;
    const MAX_TRAVERSAL_ATTEMPTS = 25;
    while (fiberNode && attempts < MAX_TRAVERSAL_ATTEMPTS) {
      if (fiberNode.stateNode && fiberNode.stateNode.props) {
        const api = findApiInObject(fiberNode.stateNode.props);
        if (api) {
          excalidrawApiInstance = api;
          break;
        }
        if (isExcalidrawAPI(fiberNode.stateNode.props.excalidrawAPI)) {
          excalidrawApiInstance = fiberNode.stateNode.props.excalidrawAPI;
          break;
        }
      }
      if (fiberNode.memoizedProps) {
        const api = findApiInObject(fiberNode.memoizedProps);
        if (api) {
          excalidrawApiInstance = api;
          break;
        }
        if (isExcalidrawAPI(fiberNode.memoizedProps.excalidrawAPI)) {
          excalidrawApiInstance = fiberNode.memoizedProps.excalidrawAPI;
          break;
        }
      }

      if (fiberNode.tag === 1 && fiberNode.stateNode && fiberNode.stateNode.state) {
        const api = findApiInObject(fiberNode.stateNode.state);
        if (api) {
          excalidrawApiInstance = api;
          break;
        }
      }

      if (
        fiberNode.tag === 0 ||
        fiberNode.tag === 2 ||
        fiberNode.tag === 14 ||
        fiberNode.tag === 15 ||
        fiberNode.tag === 11
      ) {
        if (fiberNode.memoizedState) {
          let currentHook = fiberNode.memoizedState;
          let hookAttempts = 0;
          const MAX_HOOK_ATTEMPTS = 15;
          while (currentHook && hookAttempts < MAX_HOOK_ATTEMPTS) {
            const api = findApiInObject(currentHook.memoizedState);
            if (api) {
              excalidrawApiInstance = api;
              break;
            }
            currentHook = currentHook.next;
            hookAttempts++;
          }
          if (excalidrawApiInstance) break;
        }
      }
      if (fiberNode.stateNode) {
        const api = findApiInObject(fiberNode.stateNode);
        if (api && api !== fiberNode.stateNode.props && api !== fiberNode.stateNode.state) {
          excalidrawApiInstance = api;
          break;
        }
      }
      if (
        fiberNode.tag === 9 &&
        fiberNode.memoizedProps &&
        typeof fiberNode.memoizedProps.value !== 'undefined'
      ) {
        const api = findApiInObject(fiberNode.memoizedProps.value);
        if (api) {
          excalidrawApiInstance = api;
          break;
        }
      }

      if (fiberNode.return) {
        fiberNode = fiberNode.return;
      } else {
        break;
      }
      attempts++;
    }

    if (excalidrawApiInstance) {
      window.excalidrawAPI = excalidrawApiInstance;
      console.log('现在您可以通过 `window.foundExcalidrawAPI` 在控制台访问它。');
    } else {
      console.error('在检查组件树后未能找到 excalidrawAPI。');
    }
    return excalidrawApiInstance;
  }

  function createFullExcalidrawElement(skeleton) {
    const id = Math.random().toString(36).substring(2, 9);

    const seed = Math.floor(Math.random() * 2 ** 31);
    const versionNonce = Math.floor(Math.random() * 2 ** 31);

    const defaults = {
      isDeleted: false,
      fillStyle: 'hachure',
      strokeWidth: 1,
      strokeStyle: 'solid',
      roughness: 1,
      opacity: 100,
      angle: 0,
      groupIds: [],
      strokeColor: '#000000',
      backgroundColor: 'transparent',
      version: 1,
      locked: false,
    };

    const fullElement = {
      id: id,
      seed: seed,
      versionNonce: versionNonce,
      updated: Date.now(),
      ...defaults,
      ...skeleton,
    };

    return fullElement;
  }

  let targetElementForAPI = document.querySelector('.excalidraw-app');

  if (targetElementForAPI) {
    getExcalidrawAPIFromDOM(targetElementForAPI);
  }

  const eventHandler = {
    getSceneElements: () => {
      try {
        return window.excalidrawAPI.getSceneElements();
      } catch (error) {
        return {
          error: true,
          msg: JSON.stringify(error),
        };
      }
    },
    addElement: (param) => {
      try {
        const existingElements = window.excalidrawAPI.getSceneElements();
        const newElements = [...existingElements];
        param.eles.forEach((ele, idx) => {
          const newEle = createFullExcalidrawElement(ele);
          newEle.index = `a${existingElements.length + idx + 1}`;
          newElements.push(newEle);
        });
        console.log('newElements ==>', newElements);
        const appState = window.excalidrawAPI.getAppState();
        window.excalidrawAPI.updateScene({
          elements: newElements,
          appState: appState,
          commitToHistory: true,
        });
        return {
          success: true,
        };
      } catch (error) {
        return {
          error: true,
          msg: JSON.stringify(error),
        };
      }
    },
    deleteElement: (param) => {
      try {
        const existingElements = window.excalidrawAPI.getSceneElements();
        const newElements = [...existingElements];
        const idx = newElements.findIndex((e) => e.id === param.id);
        if (idx >= 0) {
          newElements.splice(idx, 1);
          const appState = window.excalidrawAPI.getAppState();
          window.excalidrawAPI.updateScene({
            elements: newElements,
            appState: appState,
            commitToHistory: true,
          });
          return {
            success: true,
          };
        } else {
          return {
            error: true,
            msg: 'element not found',
          };
        }
      } catch (error) {
        return {
          error: true,
          msg: JSON.stringify(error),
        };
      }
    },
    updateElement: (param) => {
      try {
        const existingElements = window.excalidrawAPI.getSceneElements();
        const resIds = [];
        for (let i = 0; i < param.length; i++) {
          const idx = existingElements.findIndex((e) => e.id === param[i].id);
          if (idx >= 0) {
            resIds.push[idx];
            window.excalidrawAPI.mutateElement(existingElements[idx], { ...param[i] });
          }
        }
        return {
          success: true,
          msg: `已更新元素：${resIds.join(',')}`,
        };
      } catch (error) {
        return {
          error: true,
          msg: JSON.stringify(error),
        };
      }
    },
    cleanup: () => {
      try {
        window.excalidrawAPI.resetScene();
        return {
          success: true,
        };
      } catch (error) {
        return {
          error: true,
          msg: JSON.stringify(error),
        };
      }
    },
  };

  const handleExecution = (event) => {
    const { action, payload, requestId } = event.detail;
    const param = JSON.parse(payload || '{}');
    let data, error;
    try {
      const handler = eventHandler[action];
      if (!handler) {
        error = 'event name not found';
      }
      data = handler(param);
    } catch (e) {
      error = e.message;
    }
    window.dispatchEvent(
      new CustomEvent('chrome-mcp:response', { detail: { requestId, data, error } }),
    );
  };

  // --- Lifecycle Functions ---
  const initialize = () => {
    window.addEventListener('chrome-mcp:execute', handleExecution);
    window.addEventListener('chrome-mcp:cleanup', cleanup);
    window[SCRIPT_ID] = true;
  };

  const cleanup = () => {
    window.removeEventListener('chrome-mcp:execute', handleExecution);
    window.removeEventListener('chrome-mcp:cleanup', cleanup);
    delete window[SCRIPT_ID];
    delete window.excalidrawAPI;
  };

  initialize();
})();
