import { Button, Intent, Position, Toaster } from "@blueprintjs/core";
import ReactDOM from "react-dom";
import React from "react";
import { openFullResultsPopup } from "./full-results-popup";

// Toaster configurations
const toasterConfigs = {
  AppToaster: {
    className: "color-toaster",
    position: Position.TOP,
    intent: Intent.WARNING,
    icon: "warning-sign",
    maxToasts: 1,
    timeout: 12000,
  },
  AgentToaster: {
    className: "search-agent-toaster",
    position: Position.TOP_RIGHT,
    intent: Intent.NONE,
    isCloseButtonShown: false,
    canEscapeKeyClear: true,
    maxToasts: 1,
  },
  ThinkingToaster: {
    className: "thinking-toaster",
    position: Position.TOP,
    intent: Intent.NONE,
    isCloseButtonShown: false,
    canEscapeKeyClear: true,
    maxToasts: 1,
  },
  MCPToaster: {
    className: "mcp-toaster",
    position: Position.TOP_RIGHT,
    intent: Intent.NONE,
    isCloseButtonShown: false,
    canEscapeKeyClear: true,
    maxToasts: 1,
  },
};

// Create or recreate toaster
const createOrRecreateToaster = (name) => {
  return Toaster.create(toasterConfigs[name]);
};

// Initialize toasters
export let AppToaster = createOrRecreateToaster("AppToaster");
export let AgentToaster = createOrRecreateToaster("AgentToaster");
export let ThinkingToaster = createOrRecreateToaster("ThinkingToaster");
export let MCPToaster = createOrRecreateToaster("MCPToaster");

// Function to ensure toaster is functional, recreate if needed
export const ensureToaster = (name) => {
  const currentToaster = {
    AppToaster,
    AgentToaster,
    ThinkingToaster,
    MCPToaster,
  }[name];
  try {
    currentToaster.getToasts();
    return currentToaster;
  } catch (error) {
    // Recreate and update the export
    const newToaster = createOrRecreateToaster(name);
    if (name === "MCPToaster") MCPToaster = newToaster;
    else if (name === "ThinkingToaster") ThinkingToaster = newToaster;
    else if (name === "AgentToaster") AgentToaster = newToaster;
    else if (name === "AppToaster") AppToaster = newToaster;
    return newToaster;
  }
};

export const displayThinkingToast = (message = "", options = {}) => {
  const toastId = ThinkingToaster.show({
    message,
    timeout: 0,
    isCloseButtonShown: false,
  });
  const thinkingToasterStream = document.querySelector(
    ".thinking-toaster .bp3-toast-message"
  );
  if (thinkingToasterStream) {
    thinkingToasterStream.innerText += `\n\n`;
    addButtonsToToaster(toastId, ".thinking-toaster", ThinkingToaster, options);
  }
  return thinkingToasterStream;
};

export const displayMCPToast = (message = "", options = {}) => {
  const toastId = MCPToaster.show({
    message,
    timeout: 0,
    isCloseButtonShown: false,
  });

  // Use requestAnimationFrame to wait for DOM update, then setTimeout for render completion
  setTimeout(() => {
    const mcpToasterStream = document.querySelector(
      ".mcp-toaster .bp3-toast-message"
    );
    if (mcpToasterStream) {
      // mcpToasterStream.innerText = message + `\n\n`;
      addButtonsToToaster(toastId, ".mcp-toaster", MCPToaster, options);

      // Store the element globally so it can be accessed later
      window.mcpToasterStreamElement = mcpToasterStream;
    }
  }, 50); // Slightly longer delay to ensure full render

  // Return a function that retrieves the element
  const getToasterElement = () => {
    return (
      window.mcpToasterStreamElement ||
      document.querySelector(".mcp-toaster .bp3-toast-message")
    );
  };

  return getToasterElement();
};

// Global state for agent cancellation - shared between MCP and Search agents
let currentAgentController = null;
let currentFullResults = null;
let isAgentStopped = false;

export const setAgentController = (controller) => {
  currentAgentController = controller;
  isAgentStopped = false;
};

export const clearAgentController = () => {
  currentAgentController = null;
  isAgentStopped = false;
};

export const setAgentFullResults = (results) => {
  currentFullResults = results;
};

export const clearAgentFullResults = () => {
  currentFullResults = null;
};

export const markAgentAsStopped = () => {
  isAgentStopped = true;
};

// React component for expansion dropdown
const ExpansionDropdown = ({ expansionOptions, buttonProps, toasterElt }) => {
  const [isOpen, setIsOpen] = React.useState(false);
  const dropdownRef = React.useRef(null);
  const buttonRef = React.useRef(null);

  // Parse expansion options from text format to structured data
  const parseExpansionOptions = (optionsText) => {
    return optionsText
      .split("\n")
      .filter((line) => line.trim().startsWith("•"))
      .map((line) => {
        const text = line.replace("•", "").trim();

        // Check for strategy key format: "text|KEY:strategyKey"
        let strategyKey = null;
        let workingText = text;
        if (text.includes("|KEY:")) {
          const parts = text.split("|KEY:");
          workingText = parts[0];
          strategyKey = parts[1];
        }

        // Check for depth expansion format: "text|DEPTH:N"
        let depthTarget = null;
        let cleanText = workingText;
        if (workingText.includes("|DEPTH:")) {
          const parts = workingText.split("|DEPTH:");
          cleanText = parts[0];
          depthTarget = parseInt(parts[1]);
        }

        const emoji = cleanText.match(/^(\p{Emoji})/u)?.[1] || "🔍";
        const label = cleanText.replace(/^(\p{Emoji})\s*/u, "");

        return {
          emoji,
          label,
          action: cleanText,
          strategyKey, // Add strategy key for reliable mapping
          depthTarget, // Add depth as structured data
        };
      });
  };

  const options = parseExpansionOptions(expansionOptions);

  const handleOptionClick = (option) => {
    // Trigger expansion by dispatching a custom event that the agent can listen to
    const expansionEvent = new CustomEvent("agentExpansion", {
      detail: {
        action: option.action,
        label: option.label,
        emoji: option.emoji,
        strategyKey: option.strategyKey, // Pass strategy key for reliable mapping
        depthTarget: option.depthTarget, // Pass depth directly
      },
    });
    window.dispatchEvent(expansionEvent);

    // Update toaster message to show selected expansion
    const msgElt = toasterElt.querySelector(".bp3-toast-message");
    if (msgElt) {
      msgElt.innerText += `\n🚀 ${option.label}...`;
    }

    setIsOpen(false);
  };

  // Close dropdown when clicking outside
  React.useEffect(() => {
    const handleClickOutside = (event) => {
      // Check if click is inside the dropdown
      if (dropdownRef.current && dropdownRef.current.contains(event.target)) {
        return; // Click is inside dropdown, don't close
      }

      // Check if click is on the expansion button (look for button with "Expand Search" text)
      const expandButton = event.target.closest("button");
      if (
        expandButton &&
        expandButton.textContent &&
        expandButton.textContent.includes("Expand Search")
      ) {
        return; // Click is on the expansion button, don't close (let button handle it)
      }

      // Click is outside both dropdown and button, close dropdown
      setIsOpen(false);
    };

    if (isOpen) {
      document.addEventListener("mousedown", handleClickOutside);
      return () =>
        document.removeEventListener("mousedown", handleClickOutside);
    }
  }, [isOpen]);

  return (
    <div key="expansion" className="expansion-dropdown-container">
      <Button
        ref={buttonRef}
        text="Expand Search"
        rightIcon={isOpen ? "chevron-up" : "chevron-down"}
        {...buttonProps}
        intent="warning"
        onClick={() => setIsOpen(!isOpen)}
      />

      {isOpen && (
        <div ref={dropdownRef} className="expansion-dropdown-menu">
          {options.map((option, index) => (
            <div
              key={index}
              className="expansion-dropdown-option"
              onClick={() => handleOptionClick(option)}
            >
              <span className="expansion-dropdown-option-emoji">
                {option.emoji}
              </span>
              <span className="expansion-dropdown-option-label">
                {option.label}
              </span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

export const addButtonsToToaster = (
  _toastId,
  toasterSelector,
  toasterInstance,
  options = {}
) => {
  const toasterElt = document.querySelector(`${toasterSelector} .bp3-toast`);
  if (!toasterElt) return;
  const newDiv = document.createElement("div");
  newDiv.classList.add("buttons");
  toasterElt.appendChild(newDiv);

  const props = { minimal: true, size: "small" };

  const buttons = [];

  // Add copy button for non-agent toasters (but never for search agent)
  const isSearchAgentToaster = toasterSelector === ".search-agent-toaster";
  if (!options.showFullResultsButton && !isSearchAgentToaster) {
    buttons.push(
      <Button
        key="copy"
        text="Copy to clipboard"
        {...props}
        intent="primary"
        onClick={() => {
          const msgElt = toasterElt.querySelector(".bp3-toast-message");
          navigator.clipboard.writeText(msgElt.innerText);
        }}
      />
    );
  }

  // Add stop button for agent processing (available during execution)
  if (options.showStopButton && (currentAgentController || isAgentStopped)) {
    const handleStop = () => {
      if (currentAgentController && !isAgentStopped) {
        // Immediately abort the controller
        currentAgentController.abort();

        // Update the message immediately
        const msgElt = toasterElt.querySelector(".bp3-toast-message");
        if (msgElt) {
          msgElt.innerText += "\n🛑 Stopping agent...";
        }

        // Mark as stopped
        markAgentAsStopped();

        // Update button appearance using DOM manipulation
        setTimeout(() => {
          const stopBtn = toasterElt.querySelector(".agent-stop-button");
          if (stopBtn) {
            stopBtn.textContent = "Stopped";
            stopBtn.disabled = true;
            stopBtn.className = stopBtn.className.replace(
              "bp3-intent-danger",
              "bp3-intent-none"
            );
            // Remove stop icon
            const iconEl = stopBtn.querySelector(".bp3-icon-stop");
            if (iconEl) {
              iconEl.remove();
            }
          }
        }, 10);

        clearAgentController();
      }
    };

    buttons.unshift(
      <Button
        key="stop"
        className="agent-stop-button"
        text={isAgentStopped ? "Stopped" : "Stop"}
        {...props}
        intent={isAgentStopped ? "none" : "danger"}
        icon={isAgentStopped ? null : "stop"}
        disabled={isAgentStopped}
        onClick={handleStop}
      />
    );
  }

  // Add expansion dropdown button (available when expansion options are provided)
  if (options.showExpansionButton && options.expansionOptions) {
    const expansionButton = React.createElement(ExpansionDropdown, {
      expansionOptions: options.expansionOptions,
      buttonProps: props,
      toasterElt: toasterElt,
    });
    buttons.push(expansionButton);
  }

  // Add view full results button (available after completion)
  if (options.showFullResultsButton && currentFullResults) {
    const targetUid = window.lastAgentResponseTargetUid || null;
    const userQuery = window.lastUserQuery || null;
    const formalQuery = window.lastFormalQuery || null;
    const intentParserResult = window.lastIntentParserResult || null;

    buttons.push(
      <Button
        key="results"
        text="View Full Results"
        {...props}
        intent="primary"
        icon="list-detail-view"
        onClick={() =>
          openFullResultsPopup({
            results: currentFullResults,
            targetUid,
            userQuery,
            formalQuery,
            forceOpenChat: false,
            intentParserResult,
          })
        }
      />
    );
  }

  buttons.push(
    <Button
      key="close"
      text="Close"
      {...props}
      onClick={() => {
        if (toasterInstance) {
          toasterInstance.clear();
        } else {
          // Determine toaster name from selector and ensure it works
          const toasterName =
            toasterSelector === ".mcp-toaster"
              ? "MCPToaster"
              : toasterSelector === ".thinking-toaster"
              ? "ThinkingToaster"
              : toasterSelector === ".search-agent-toaster"
              ? "AgentToaster"
              : toasterSelector === ".color-toaster"
              ? "AppToaster"
              : null;

          if (toasterName) {
            ensureToaster(toasterName).clear();
          }
        }
      }}
    />
  );

  const buttonSectionJSX = <>{buttons}</>;

  ReactDOM.render(buttonSectionJSX, newDiv);
};

// Re-export openFullResultsPopup from its new location for backward compatibility
export { openFullResultsPopup } from "./full-results-popup";
