import $ from "jquery";
import "jstree";
import { api } from "../../../services/api";
import { getCurrentUser } from "../../../services/authState";
import type { FolderTreeResponse } from "../../../types";
import { confirmDialog, notify, notifyError, promptDialog } from "../../../ui/dialogs";
import { appState } from "../appState";
import { loadModels } from "./models";

type JsTreeNode = {
  id: string;
  text: string;
};

function isRealFolderId(id: string) {
  return /^\d+$/.test(id);
}

function selectFolder(node: JsTreeNode) {
  appState.selectedFolderId = Number(node.id);
  appState.selectedFolderName = appState.folders.find((folder) => folder.id === Number(node.id))?.name ?? node.text;
}

async function createFolder(parentId: number | null) {
  const name = await promptDialog({ title: "新建目录", label: "目录名称" });
  if (!name) return;
  await api("/api/folders", {
    method: "POST",
    body: JSON.stringify({ parentId, name })
  });
  await loadFolders();
}

async function renameFolder(folderId: number | null) {
  if (!folderId) return notify("请先选择目录");
  const current = appState.folders.find((folder) => folder.id === folderId);
  if (!current?.parent_id) return notify("根目录不能重命名");
  const name = await promptDialog({ title: "重命名目录", label: "目录名称", value: current.name });
  if (!name) return;
  await api(`/api/folders/${folderId}`, {
    method: "PUT",
    body: JSON.stringify({ name })
  });
  await loadFolders();
}

async function deleteFolder(folderId: number | null) {
  if (!folderId) return notify("请先选择目录");
  const current = appState.folders.find((folder) => folder.id === folderId);
  if (!current?.parent_id) return notify("根目录不能删除");
  const confirmed = await confirmDialog("删除目录会删除目录下所有模型和子目录，是否继续？");
  if (!confirmed) return;
  await api(`/api/folders/${folderId}`, { method: "DELETE" });
  appState.selectedFolderId = null;
  await loadFolders();
}

async function runFolderAction(action: () => Promise<void>) {
  try {
    await action();
  } catch (error) {
    notifyError(error);
  }
}

export async function loadFolders(options: { reloadModels?: boolean } = {}) {
  const reloadModels = options.reloadModels ?? true;
  const result = await api<FolderTreeResponse>("/api/folders");
  appState.folders = result.folders;
  const root = appState.folders.find((folder) => folder.parent_id === null);
  appState.selectedFolderId ??= root?.id ?? null;
  appState.selectedFolderName = appState.folders.find((folder) => folder.id === appState.selectedFolderId)?.name ?? "";

  $("#folderTree").jstree("destroy");
  $("#folderTree").jstree({
    core: {
      data: result.tree,
      multiple: false
    },
    plugins: ["contextmenu"],
    contextmenu: {
      items(node: JsTreeNode) {
        if (!isRealFolderId(node.id)) return {};
        const folderId = Number(node.id);
        const folder = appState.folders.find((item) => item.id === folderId);
        const canWrite = Boolean(folder?.permissions.write);
        const isSystem = Boolean(folder?.is_system);
        return {
          create: {
            label: "新建目录",
            icon: "tree-menu-icon tree-menu-icon-add",
            _disabled: !canWrite,
            action: () => runFolderAction(async () => {
              selectFolder(node);
              await createFolder(folderId);
            })
          },
          rename: {
            label: "重命名",
            icon: "tree-menu-icon tree-menu-icon-edit",
            _disabled: !canWrite || isSystem,
            action: () => runFolderAction(async () => {
              selectFolder(node);
              await renameFolder(folderId);
            })
          },
          remove: {
            label: "删除",
            icon: "tree-menu-icon tree-menu-icon-delete",
            _disabled: !canWrite || isSystem,
            action: () => runFolderAction(async () => {
              selectFolder(node);
              await deleteFolder(folderId);
            })
          }
        };
      }
    }
  }).on("select_node.jstree", async (_event: JQuery.Event, data: { node: { id: string; text: string } }) => {
    if (!isRealFolderId(data.node.id)) return;
    appState.selectedFolderId = Number(data.node.id);
    appState.selectedFolderName = appState.folders.find((folder) => folder.id === appState.selectedFolderId)?.name ?? data.node.text;
    appState.page = 1;
    await loadModels();
  });

  if (appState.selectedFolderId) {
    $("#folderTree").on("ready.jstree", () => {
      $("#folderTree").jstree(true).select_node(String(appState.selectedFolderId), true);
    });
  }
  if (reloadModels) {
    await loadModels();
  }
}
