import { computed, ref } from "vue";
import type { MdtodoTaskLinkRecord, MdtodoTaskRecord, MdtodoTaskStatus } from "@/api";
import type { ApiError, ErrorDiagnostic } from "@/types";
import { fileDisplayName } from "@/composables/mdtodo/useMdtodoDisplay";
import type { useMdtodoReportPreview } from "@/composables/mdtodo/useMdtodoReportPreview";
import type { useMdtodoSource } from "@/composables/mdtodo/useMdtodoSource";
import type { useMdtodoTaskData } from "@/composables/mdtodo/useMdtodoTaskData";
import type { useMdtodoViewState } from "@/composables/mdtodo/useMdtodoViewState";
import type { useMdtodoWorkbenchLaunch } from "@/composables/mdtodo/useMdtodoWorkbenchLaunch";

export type MdtodoRefreshMode = "blocking" | "persistent";

export function useMdtodoWorkspaceState(dependencies: {
  source: ReturnType<typeof useMdtodoSource>;
  taskData: ReturnType<typeof useMdtodoTaskData>;
  report: ReturnType<typeof useMdtodoReportPreview>;
  launch: ReturnType<typeof useMdtodoWorkbenchLaunch>;
  viewState: ReturnType<typeof useMdtodoViewState>;
}) {
  const { source, taskData, report, launch, viewState } = dependencies;
  const loading = ref(false);
  const error = ref<string | null>(null);
  const apiError = ref<ApiError | null>(null);
  const diagnostic = ref<ErrorDiagnostic | null>(null);
  const selectedSourceId = ref<string | null>(null);
  const selectedFileRef = ref<string | null>(null);
  const selectedTaskRef = ref<string | null>(null);
  const collapsedTaskRefs = ref(new Set<string>());
  const taskPaneWidth = ref(25);
  const queuePaneWidth = ref(40);
  const taskPaneCollapsed = ref(false);
  const reportPaneWidth = ref(48);
  const reportPaneCollapsed = ref(false);
  const refreshMode = ref<MdtodoRefreshMode>("blocking");
  const showInfo = ref(false);
  const showSourceConfig = ref(false);
  const showTaskCreate = ref(false);
  const editingTitle = ref(false);
  const editingBody = ref(false);
  const editTitle = ref("");
  const editStatus = ref<MdtodoTaskStatus>("open");
  const editBody = ref("");
  const newTaskTitle = ref("");
  const newTaskBody = ref("");
  const deleteConfirm = ref(false);
  const providerProfile = ref("");
  const providerOptions = ref<
    Array<{ value: string; label: string; configured?: boolean }>
  >([]);
  const providerReady = ref(false);
  const providerError = ref<string | null>(null);
  const selectedSource = computed(
    () =>
      source.sources.value.find(
        (item) => item.sourceId === selectedSourceId.value,
      ) ?? null,
  );
  const selectedFile = computed(
    () =>
      taskData.files.value.find(
        (item) => item.fileRef === selectedFileRef.value,
      ) ?? null,
  );
  const selectedTask = computed(
    () =>
      taskData.tasks.value.find(
        (item) => item.taskRef === selectedTaskRef.value,
      ) ?? null,
  );
  const selectedTaskProjection = computed(() =>
    selectedTaskRef.value
      ? (taskData.taskByRef.value.get(selectedTaskRef.value) ?? null)
      : null,
  );
  const fileTasks = computed(() =>
    selectedFileRef.value
      ? taskData.tasks.value.filter(
          (item) => item.fileRef === selectedFileRef.value,
        )
      : taskData.tasks.value,
  );
  const currentTaskDetail = computed(() =>
    taskData.taskDetail.value?.taskRef === selectedTaskRef.value
      ? taskData.taskDetail.value
      : null,
  );
  const taskSearch = computed({
    get: () => viewState.search.value,
    set: (value: string) => {
      void viewState.update({ search: value }, true);
    },
  });
  const taskStatus = computed({
    get: () => viewState.status.value,
    set: (value: typeof viewState.status.value) => {
      void viewState.update({ status: value }, true);
    },
  });
  const filteredTasks = computed(() => {
    const query = taskSearch.value.trim().toLowerCase();
    return fileTasks.value.filter((task) => {
      const statusMatches =
        taskStatus.value === "all" ||
        (task.status || "unknown") === taskStatus.value;
      const textMatches =
        !query ||
        [task.taskId, task.title, task.taskRef].some((value) =>
          String(value || "")
            .toLowerCase()
            .includes(query),
        );
      return statusMatches && textMatches;
    });
  });
  const taskDetailPartial = computed(
    () => taskData.taskDetailAuthority.value?.state === "unavailable",
  );
  const mutationDisabled = computed(() =>
    Boolean(
      selectedTask.value &&
        (taskData.taskDetailLoading.value ||
          !currentTaskDetail.value ||
          taskDetailPartial.value),
    ),
  );
  const createDisabledReason = computed(() => {
    if (!selectedSourceId.value) return "请先选择 Source";
    if (!selectedFileRef.value) return "请先选择 MDTODO 文件";
    if (!selectedFile.value?.fingerprint)
      return "文件 fingerprint 不可用，重建索引后再创建任务";
    if (taskDetailPartial.value)
      return "当前详情来自离线投影，Node 恢复后才能创建任务";
    if (
      selectedTask.value &&
      (taskData.taskDetailLoading.value || !currentTaskDetail.value)
    )
      return "任务详情 authority 尚未确认，请稍候";
    return null;
  });
  const createDisabled = computed(() => Boolean(createDisabledReason.value));
  const selectedTaskBody = computed(
    () =>
      currentTaskDetail.value?.body ??
      selectedTask.value?.bodyPreview ??
      selectedTaskProjection.value?.bodyPreview ??
      "",
  );
  const selectedTaskLinks = computed(() => {
    const detailLinks = markdownReportLinks(
      currentTaskDetail.value?.links ?? [],
    );
    if (detailLinks.length) return detailLinks;
    const projectedLinks = markdownReportLinks(
      selectedTask.value?.links ?? selectedTaskProjection.value?.links ?? [],
    );
    if (projectedLinks.length) {
      return taskDetailPartial.value
        ? projectedLinks.map(unavailableReportLink)
        : projectedLinks;
    }
    const linkCount = Number(
      selectedTask.value?.linkCount ??
        selectedTaskProjection.value?.linkCount ??
        0,
    );
    return selectedTask.value && linkCount > 0
      ? [projectedReportLink(selectedTask.value, linkCount)]
      : [];
  });
  const selectedFileName = computed(() =>
    selectedFile.value
      ? fileDisplayName(selectedFile.value)
      : selectedTask.value?.fileRef || "-",
  );
  const selectedTaskBodyHtml = computed(() =>
    report.markdownToHtml(selectedTaskBody.value),
  );
  const reportPreviewHtml = computed(() =>
    report.markdownToHtml(report.reportPreview.value?.content ?? ""),
  );
  const reportOpen = computed(() => Boolean(report.reportPreview.value));
  const taskStatusCounts = computed(() =>
    fileTasks.value.reduce<Record<string, number>>((counts, task) => {
      const key = task.status || "unknown";
      counts[key] = (counts[key] ?? 0) + 1;
      return counts;
    }, {}),
  );
  const providerBlocker = computed(() => {
    if (!providerReady.value) return "模型通道校验中";
    if (providerError.value) return providerError.value;
    if (!providerProfile.value) return "模型通道未选择";
    const option = providerOptions.value.find(
      (item) => item.value === providerProfile.value,
    );
    return option?.configured === false
      ? `模型通道 ${providerProfile.value} 未配置`
      : null;
  });
  const launchBlocker = computed(() =>
    launch.isLaunchEnabled(source.navigation.value)
      ? providerBlocker.value
      : "Workbench Launch capability unavailable",
  );
  const launchDisabled = computed(
    () =>
      !selectedTask.value ||
      Boolean(launchBlocker.value) ||
      launch.launchLoading.value,
  );

  return {
    loading,
    error,
    apiError,
    diagnostic,
    selectedSourceId,
    selectedFileRef,
    selectedTaskRef,
    collapsedTaskRefs,
    taskPaneWidth,
    queuePaneWidth,
    taskPaneCollapsed,
    reportPaneWidth,
    reportPaneCollapsed,
    refreshMode,
    showInfo,
    showSourceConfig,
    showTaskCreate,
    editingTitle,
    editingBody,
    editTitle,
    editStatus,
    editBody,
    newTaskTitle,
    newTaskBody,
    deleteConfirm,
    providerProfile,
    providerOptions,
    providerReady,
    providerError,
    selectedSource,
    selectedFile,
    selectedTask,
    selectedTaskProjection,
    fileTasks,
    currentTaskDetail,
    taskSearch,
    taskStatus,
    filteredTasks,
    taskDetailPartial,
    mutationDisabled,
    createDisabledReason,
    createDisabled,
    selectedTaskBody,
    selectedTaskLinks,
    selectedFileName,
    selectedTaskBodyHtml,
    reportPreviewHtml,
    reportOpen,
    taskStatusCounts,
    launchBlocker,
    launchDisabled,
  };
}

export type MdtodoWorkspaceState = ReturnType<typeof useMdtodoWorkspaceState>;

function markdownReportLinks(
  links: MdtodoTaskLinkRecord[],
): MdtodoTaskLinkRecord[] {
  return links.filter((link) => link.kind === "markdown-report");
}

function projectedReportLink(
  task: MdtodoTaskRecord,
  linkCount: number,
): MdtodoTaskLinkRecord {
  return {
    linkId: `projected-report-unavailable-${task.taskRef}`,
    label:
      linkCount === 1
        ? `${task.taskId || task.rxxId} 报告`
        : `${task.taskId || task.rxxId} 报告 (${linkCount})`,
    href: "",
    kind: "markdown-report",
    relativePath: null,
    ordinal: 1,
    availability: "projected-link-unavailable",
    message:
      "任务投影确认存在报告链接；恢复 HWPOD 详情读取或重建索引后可打开。",
    valuesRedacted: true,
  };
}

function unavailableReportLink(
  link: MdtodoTaskLinkRecord,
): MdtodoTaskLinkRecord {
  return {
    ...link,
    availability: "projected-link-unavailable",
    message: "报告索引可用，但 HWPOD 源当前不可读。",
    valuesRedacted: true,
  };
}
