import { providerProfilesAPI, type MdtodoTaskLinkRecord, type MdtodoTaskMutationInput, type MdtodoTaskRecord } from "@/api";
import type { ProviderProfileCatalogResponse } from "@/types";
import type { Router, RouteLocationNormalizedLoaded } from "vue-router";
import type { useMdtodoReportPreview } from "@/composables/mdtodo/useMdtodoReportPreview";
import type { useMdtodoSource } from "@/composables/mdtodo/useMdtodoSource";
import type { useMdtodoTaskData } from "@/composables/mdtodo/useMdtodoTaskData";
import type { useMdtodoTaskMutation } from "@/composables/mdtodo/useMdtodoTaskMutation";
import type { useMdtodoViewState } from "@/composables/mdtodo/useMdtodoViewState";
import type { useMdtodoWorkbenchLaunch } from "@/composables/mdtodo/useMdtodoWorkbenchLaunch";
import type { MdtodoWorkspaceNavigation } from "@/composables/mdtodo/useMdtodoWorkspaceNavigation";
import type { MdtodoWorkspaceState } from "@/composables/mdtodo/useMdtodoWorkspaceState";

export function useMdtodoWorkspaceActions(dependencies: {
  router: Router;
  route: RouteLocationNormalizedLoaded;
  source: ReturnType<typeof useMdtodoSource>;
  taskData: ReturnType<typeof useMdtodoTaskData>;
  mutation: ReturnType<typeof useMdtodoTaskMutation>;
  report: ReturnType<typeof useMdtodoReportPreview>;
  launch: ReturnType<typeof useMdtodoWorkbenchLaunch>;
  viewState: ReturnType<typeof useMdtodoViewState>;
  state: MdtodoWorkspaceState;
  navigation: MdtodoWorkspaceNavigation;
}) {
  const { router, route, source, taskData, mutation, report, launch, viewState, state, navigation } = dependencies;
  const { selectSource, reloadWindow, syncRoute, loadWindow } = navigation;
  const {
    selectedSourceId, selectedFileRef, selectedTaskRef, selectedSource,
    selectedFile, selectedTask, currentTaskDetail, taskDetailPartial,
    mutationDisabled, createDisabledReason, editTitle, editStatus, editBody, editingTitle,
    editingBody, newTaskTitle, newTaskBody, showTaskCreate, deleteConfirm,
    selectedTaskLinks, selectedTaskBody, selectedFileName, reportPaneCollapsed,
    launchDisabled, showSourceConfig, providerProfile, providerOptions,
    providerReady, providerError,
  } = state;
  function taskFingerprint(): string | undefined {
    return (
      selectedTask.value?.sourceFingerprint ||
      selectedFile.value?.fingerprint ||
      undefined
    );
  }

  function rejectMutation(): boolean {
    if (!mutationDisabled.value) return false;
    mutation.taskMutationMessage.value = null;
    mutation.taskMutationError.value =
      "当前仅有最近一次任务投影；Node 恢复并读到源 Markdown 后才能写入。";
    return true;
  }

  function resetEditor(task: MdtodoTaskRecord | null): void {
    editingTitle.value = false;
    editingBody.value = false;
    editTitle.value = task?.title || "";
    editStatus.value = task?.status || "open";
    const detail = taskData.taskDetail.value;
    editBody.value =
      detail && detail.taskRef === task?.taskRef ? detail.body || "" : "";
    deleteConfirm.value = false;
  }

  async function saveBasics(): Promise<void> {
    if (rejectMutation() || !selectedTask.value) return;
    const input: MdtodoTaskMutationInput = {
      expectedFingerprint: taskFingerprint(),
    };
    if (
      editTitle.value.trim() &&
      editTitle.value.trim() !== selectedTask.value.title
    )
      input.title = editTitle.value.trim();
    if (editStatus.value !== (selectedTask.value.status || "open"))
      input.status = editStatus.value;
    if (!input.title && !input.status)
      mutation.taskMutationMessage.value = "任务标题和状态没有变化";
    else if (
      await mutation.updateTask(
        selectedTask.value.taskRef,
        input,
        "任务已保存",
        reloadWindow,
      )
    )
      editingTitle.value = false;
  }

  async function saveBody(): Promise<void> {
    if (rejectMutation() || !selectedTask.value) return;
    if (
      await mutation.updateTask(
        selectedTask.value.taskRef,
        { expectedFingerprint: taskFingerprint(), body: editBody.value },
        "正文已保存",
        reloadWindow,
      )
    )
      editingBody.value = false;
  }

  async function createTask(
    kind: "root" | "subtask" | "continue",
  ): Promise<void> {
    if (rejectMutation()) return;
    const sourceId = selectedSourceId.value;
    const fileRef = selectedFileRef.value;
    if (!sourceId || !fileRef) {
      mutation.taskMutationError.value =
        createDisabledReason.value || "请先选择 MDTODO 文件";
      return;
    }
    const title = newTaskTitle.value.trim();
    if (!title) {
      mutation.taskMutationError.value = "新任务标题不能为空";
      return;
    }
    const input: MdtodoTaskMutationInput = {
      sourceId,
      fileRef,
      expectedFingerprint: taskFingerprint(),
      title,
      body: newTaskBody.value,
    };
    if (kind === "subtask" && selectedTask.value)
      input.parentTaskRef = selectedTask.value.taskRef;
    if (kind === "continue" && selectedTask.value)
      input.afterTaskRef = selectedTask.value.taskRef;
    const nextTaskRef = await mutation.createTask(
      input,
      "任务已创建",
      async () => {},
    );
    if (nextTaskRef) {
      report.closeReportPreview();
      newTaskTitle.value = "";
      newTaskBody.value = "";
      showTaskCreate.value = false;
      const loaded = await loadWindow(sourceId, {
        fileRef,
        taskId: nextTaskRef,
        updateRoute: false,
        mode: "persistent",
      });
      if (!loaded) {
        mutation.taskMutationMessage.value =
          "任务已创建；任务索引刷新失败，请重试";
        return;
      }
      await syncRoute(false);
    }
  }

  async function deleteTask(): Promise<void> {
    if (rejectMutation() || !selectedTask.value) return;
    if (!deleteConfirm.value) {
      deleteConfirm.value = true;
      mutation.taskMutationMessage.value = "再次点击确认删除当前任务及子任务";
      return;
    }
    const deletedTaskRef = selectedTask.value.taskRef;
    const expectedFingerprint = taskFingerprint();
    const fallbackTaskRef =
      taskData.tasks.value.find((task) => task.taskRef !== deletedTaskRef)
        ?.taskRef ?? null;
    const previousTaskRef = selectedTaskRef.value;
    selectedTaskRef.value = null;
    const reloadAfterDelete = async () => {
      if (selectedSourceId.value) {
        await loadWindow(selectedSourceId.value, {
          fileRef: selectedFileRef.value,
          taskId: null,
          updateRoute: false,
          mode: "persistent",
        });
      }
    };
    const result = await mutation.deleteTask(
      deletedTaskRef,
      { expectedFingerprint },
      reloadAfterDelete,
    );
    if (!result) {
      selectedTaskRef.value = previousTaskRef;
      return;
    }
    report.closeReportPreview();
    deleteConfirm.value = false;
    selectedTaskRef.value =
      taskData.tasks.value.find((task) => task.taskRef !== deletedTaskRef)
        ?.taskRef ?? fallbackTaskRef;
    await syncRoute(false, null);
  }

  async function openReport(link: MdtodoTaskLinkRecord): Promise<void> {
    if (
      !selectedTaskRef.value ||
      !(await report.openReportPreview(selectedTaskRef.value, link))
    )
      return;
    reportPaneCollapsed.value = false;
    await syncRoute();
    await viewState.update({ tab: "report" }, true);
  }

  async function closeReport(): Promise<void> {
    report.closeReportPreview();
    await syncRoute(false, null);
    if (viewState.tab.value === "report")
      await viewState.update({ tab: "document" }, true);
  }

  async function launchWorkbench(): Promise<void> {
    if (!selectedTask.value || launchDisabled.value) return;
    const target = launch.openWorkbenchTarget();
    const result = await launch.launchTask(
      selectedTask.value,
      selectedTaskBody.value,
      selectedTaskLinks.value,
      selectedFileName.value,
      source.navigation.value,
      providerProfile.value,
    );
    if (result) {
      await launch.navigatePreparedTarget(result, target);
      await taskData.loadLinks(selectedTask.value.taskRef);
    } else {
      launch.closeWorkbenchTarget(target);
    }
  }

  function openSourceConfig(): void {
    source.openSourceForm(selectedSource.value);
    showSourceConfig.value = true;
  }
  async function saveSource(): Promise<void> {
    const sourceId = await source.saveSourceConfig();
    if (sourceId) {
      showSourceConfig.value = false;
      await selectSource(sourceId);
    }
  }
  function setProvider(value: string): void {
    providerProfile.value = value;
    const query = { ...route.query };
    value ? (query.provider = value) : delete query.provider;
    void router.replace({ query });
  }
  async function loadProviders(): Promise<void> {
    providerReady.value = false;
    const response = await providerProfilesAPI.catalog();
    providerReady.value = true;
    if (!response.ok) {
      providerError.value = "模型通道目录不可用";
      return;
    }
    providerOptions.value = providerCatalogOptions(response.data);
    const requested =
      typeof route.query.provider === "string" ? route.query.provider : "";
    const requestedAvailable = providerOptions.value.some(
      (item) => item.value === requested && item.configured !== false,
    );
    setProvider(
      requestedAvailable
        ? requested
        : providerOptions.value.find((item) => item.configured !== false)
            ?.value || "",
    );
  }

  return {
    taskFingerprint,
    rejectMutation,
    resetEditor,
    saveBasics,
    saveBody,
    createTask,
    deleteTask,
    openReport,
    closeReport,
    launchWorkbench,
    openSourceConfig,
    saveSource,
    setProvider,
    loadProviders,
  };
}

function providerCatalogOptions(
  payload: ProviderProfileCatalogResponse | null,
) {
  return (payload?.items ?? []).map((item) => ({
    value: item.profile,
    label: item.profile,
    configured: item.configured,
  }));
}
