import {
  createCompatPayloadPatch,
  createLayoutCommand,
  createThemeCommand,
  createToolbarKernelCommand,
  type MindmapCompatPayloadPatch,
  type MindmapKernelCommand,
  type MindmapNodeInput,
} from "./mindmap-command-diff";
import type { MindmapUiActionId } from "./mindmap-ui-schema";

export type MindmapActionTarget = "runtimeCommand" | "kernelCommand" | "compatPatch" | "localView";

export type MindmapRuntimeViewMethod = "centerRoot" | "zoomIn" | "zoomOut" | "fitView";

export type MindmapActionMapping = {
  actionId: MindmapUiActionId;
  target: MindmapActionTarget;
  runtimeCommand?: string;
  runtimeMethod?: MindmapRuntimeViewMethod;
  requiresActiveNode: boolean;
  readonlyAllowed: boolean;
  compatPath?: (activeNodeId: string | null) => string | null;
};

export type MindmapActionCommandInput = {
  actionId: MindmapUiActionId;
  mindmapId: string;
  activeNodeId?: string | null;
  value?: unknown;
  node?: MindmapNodeInput;
  themeConfig?: unknown;
  source?: MindmapCompatPayloadPatch["source"];
  runtimeRevision?: number | null;
  kernelRevision?: number | null;
};

export type MindmapActionCommandResult = {
  runtimeCommand?: string;
  command?: MindmapKernelCommand | MindmapCompatPayloadPatch;
};

const nodeDataPath = (field: string) => (activeNodeId: string | null): string | null =>
  activeNodeId ? `nodes.${activeNodeId}.data.${field}` : null;

const mappings: MindmapActionMapping[] = [
  { actionId: "undo", target: "runtimeCommand", runtimeCommand: "BACK", requiresActiveNode: false, readonlyAllowed: false },
  { actionId: "redo", target: "runtimeCommand", runtimeCommand: "FORWARD", requiresActiveNode: false, readonlyAllowed: false },
  { actionId: "editNode", target: "localView", requiresActiveNode: true, readonlyAllowed: false },
  { actionId: "insertSiblingAfter", target: "runtimeCommand", runtimeCommand: "INSERT_NODE", requiresActiveNode: true, readonlyAllowed: false },
  { actionId: "insertChild", target: "runtimeCommand", runtimeCommand: "INSERT_CHILD_NODE", requiresActiveNode: true, readonlyAllowed: false },
  { actionId: "deleteNode", target: "runtimeCommand", runtimeCommand: "REMOVE_NODE", requiresActiveNode: true, readonlyAllowed: false },
  { actionId: "summary", target: "runtimeCommand", runtimeCommand: "ADD_GENERALIZATION", requiresActiveNode: true, readonlyAllowed: false },
  { actionId: "associativeLine", target: "compatPatch", runtimeCommand: "ADD_ASSOCIATIVE_LINE", requiresActiveNode: true, readonlyAllowed: false },
  { actionId: "setTheme", target: "kernelCommand", requiresActiveNode: false, readonlyAllowed: false },
  { actionId: "setLayout", target: "kernelCommand", requiresActiveNode: false, readonlyAllowed: false },
  { actionId: "tag", target: "compatPatch", requiresActiveNode: true, readonlyAllowed: false, compatPath: nodeDataPath("tag") },
  { actionId: "hyperlink", target: "compatPatch", requiresActiveNode: true, readonlyAllowed: false, compatPath: nodeDataPath("hyperlink") },
  { actionId: "note", target: "compatPatch", requiresActiveNode: true, readonlyAllowed: false, compatPath: nodeDataPath("note") },
  { actionId: "image", target: "compatPatch", requiresActiveNode: true, readonlyAllowed: false, compatPath: nodeDataPath("image") },
  { actionId: "icon", target: "compatPatch", requiresActiveNode: true, readonlyAllowed: false, compatPath: nodeDataPath("icon") },
  { actionId: "formula", target: "compatPatch", requiresActiveNode: true, readonlyAllowed: false, compatPath: nodeDataPath("formula") },
  { actionId: "painter", target: "compatPatch", requiresActiveNode: true, readonlyAllowed: false, compatPath: nodeDataPath("style") },
  { actionId: "import", target: "compatPatch", requiresActiveNode: false, readonlyAllowed: false, compatPath: () => "import" },
  // 导出能力暂缓：UI state 会禁用该入口，这里不能继续下发未受控的 runtime EXPORT 命令。
  { actionId: "export", target: "localView", requiresActiveNode: false, readonlyAllowed: true },
  { actionId: "centerRoot", target: "localView", runtimeMethod: "centerRoot", requiresActiveNode: false, readonlyAllowed: true },
  { actionId: "zoomIn", target: "localView", runtimeMethod: "zoomIn", requiresActiveNode: false, readonlyAllowed: true },
  { actionId: "zoomOut", target: "localView", runtimeMethod: "zoomOut", requiresActiveNode: false, readonlyAllowed: true },
  { actionId: "fitView", target: "localView", runtimeMethod: "fitView", requiresActiveNode: false, readonlyAllowed: true },
  { actionId: "fullscreenCanvas", target: "localView", requiresActiveNode: false, readonlyAllowed: true },
  { actionId: "fullscreenPage", target: "localView", requiresActiveNode: false, readonlyAllowed: true },
  { actionId: "exitFullscreen", target: "localView", requiresActiveNode: false, readonlyAllowed: true },
  { actionId: "search", target: "localView", requiresActiveNode: false, readonlyAllowed: true },
  { actionId: "showMenu", target: "localView", requiresActiveNode: false, readonlyAllowed: true },
  { actionId: "expandCollapse", target: "localView", requiresActiveNode: true, readonlyAllowed: false },
  { actionId: "copyNodeText", target: "localView", requiresActiveNode: true, readonlyAllowed: true },
  { actionId: "readonly", target: "localView", requiresActiveNode: false, readonlyAllowed: true },
];

export const listMindmapActionMappings = (): MindmapActionMapping[] => mappings;

export const getMindmapActionMapping = (actionId: MindmapUiActionId): MindmapActionMapping | null =>
  mappings.find((mapping) => mapping.actionId === actionId) ?? null;

const readActiveNodeId = (value: string | null | undefined): string | null => {
  const trimmed = value?.trim();
  return trimmed ? trimmed : null;
};

export const mapMindmapActionToCommand = (input: MindmapActionCommandInput): MindmapActionCommandResult | null => {
  const mapping = getMindmapActionMapping(input.actionId);
  if (!mapping) return null;

  const activeNodeId = readActiveNodeId(input.activeNodeId);
  if (mapping.requiresActiveNode && !activeNodeId) return null;

  if (input.actionId === "setTheme") {
    return { command: createThemeCommand(input.mindmapId, input.value, input.themeConfig) };
  }
  if (input.actionId === "setLayout") {
    return { command: createLayoutCommand(input.mindmapId, input.value) };
  }
  if (input.actionId === "editNode") {
    return {
      command: {
        type: "updateText",
        mindmapId: input.mindmapId,
        nodeId: activeNodeId ?? "root",
        text: typeof input.value === "string" ? input.value : "",
      },
    };
  }

  if (mapping.runtimeCommand && ["INSERT_CHILD_NODE", "INSERT_NODE", "DELETE_NODE", "REMOVE_NODE"].includes(mapping.runtimeCommand)) {
    const command = createToolbarKernelCommand({
      mindmapId: input.mindmapId,
      runtimeCommand: mapping.runtimeCommand,
      activeNodeId,
      newNode: input.node,
    });
    return command ? { runtimeCommand: mapping.runtimeCommand, command } : { runtimeCommand: mapping.runtimeCommand };
  }

  if (mapping.compatPath) {
    const path = mapping.compatPath(activeNodeId);
    if (!path) return null;
    return {
      command: createCompatPayloadPatch({
        mindmapId: input.mindmapId,
        path,
        value: input.value ?? true,
        source: input.source ?? "toolbar",
        actionId: input.actionId,
        runtimeRevision: input.runtimeRevision,
        kernelRevision: input.kernelRevision,
      }),
    };
  }

  if (mapping.runtimeCommand) {
    return { runtimeCommand: mapping.runtimeCommand };
  }

  return {};
};
