// SPEC: PJ2026-01040409 MDTODO前端重写; draft-2026-06-26-p0-mdtodo-web-rewrite.
// Responsibility: MDTODO source list, HWPOD-bound source config, probe and reindex via public API.

import { reactive, ref } from "vue";
import { projectManagementAPI, type ProjectSource, type ProjectSourceInput, type ProjectNavigationResponse } from "@/api";
import type { ApiError, ErrorDiagnostic } from "@/types";

export interface UseMdtodoSourceReturn {
  sources: ReturnType<typeof ref<ProjectSource[]>>;
  navigation: ReturnType<typeof ref<ProjectNavigationResponse | null>>;
  sourceForm: ReturnType<typeof reactive<ProjectSourceInput>>;
  sourceMessage: ReturnType<typeof ref<string | null>>;
  sourceError: ReturnType<typeof ref<string | null>>;
  sourceSaving: ReturnType<typeof ref<boolean>>;
  sourceProbeLoading: ReturnType<typeof ref<boolean>>;
  sourceReindexLoading: ReturnType<typeof ref<boolean>>;
  loadNavigationAndSources: () => Promise<{ navigation: ProjectNavigationResponse | null; sources: ProjectSource[] }>;
  openSourceForm: (source: ProjectSource | null) => void;
  saveSourceConfig: () => Promise<string | null>;
  probeSource: (sourceId?: string | null) => Promise<void>;
  reindexSource: (sourceId: string) => Promise<{ documentCount: number; taskCount: number } | null>;
  clearSourceMessages: () => void;
}

function apiErrorOf(err: unknown): { error: string; apiError: ApiError | null; diagnostic: ErrorDiagnostic | null } {
  if (err && typeof err === "object" && "error" in err) {
    const result = err as { error?: string | null; apiError?: ApiError | null; diagnostic?: ErrorDiagnostic | null; status?: number };
    return { error: result.error || `HTTP ${result.status ?? "unknown"}`, apiError: result.apiError ?? null, diagnostic: result.diagnostic ?? null };
  }
  return { error: err instanceof Error ? err.message : String(err || "MDTODO source 操作失败"), apiError: null, diagnostic: null };
}

export function useMdtodoSource() {
  const sources = ref<ProjectSource[]>([]);
  const navigation = ref<ProjectNavigationResponse | null>(null);
  const sourceForm = reactive<ProjectSourceInput>({
    sourceId: "",
    sourceKind: "hwpod-workspace",
    displayName: "",
    projectId: "project_hwlab_v03",
    hwpodId: "",
    nodeId: "",
    workspaceRootRef: "",
    mdtodoRootRef: "docs/MDTODO/",
    maxFiles: 120
  });
  const sourceMessage = ref<string | null>(null);
  const sourceError = ref<string | null>(null);
  const sourceSaving = ref(false);
  const sourceProbeLoading = ref(false);
  const sourceReindexLoading = ref(false);

  async function loadNavigationAndSources(): Promise<{ navigation: ProjectNavigationResponse | null; sources: ProjectSource[] }> {
    const [navigationResponse, sourceResponse] = await Promise.all([projectManagementAPI.navigation(), projectManagementAPI.sources()]);
    if (!navigationResponse.ok) throw navigationResponse;
    if (!sourceResponse.ok) throw sourceResponse;
    navigation.value = navigationResponse.data ?? null;
    sources.value = sourceResponse.data?.sources ?? [];
    return { navigation: navigation.value, sources: sources.value };
  }

  function openSourceForm(source: ProjectSource | null): void {
    sourceMessage.value = null;
    sourceError.value = null;
    Object.assign(sourceForm, {
      sourceId: source?.sourceKind === "hwpod-workspace" ? source.sourceId : "",
      sourceKind: "hwpod-workspace",
      displayName: source?.sourceKind === "hwpod-workspace" ? source.displayName : "",
      projectId: source?.projectId || "project_hwlab_v03",
      hwpodId: source?.hwpodId || "",
      nodeId: source?.nodeId || "",
      workspaceRootRef: source?.workspaceRootRef || "",
      mdtodoRootRef: source?.mdtodoRootRef || "docs/MDTODO/",
      maxFiles: source?.maxFiles || 120
    });
  }

  async function saveSourceConfig(): Promise<string | null> {
    sourceSaving.value = true;
    sourceMessage.value = null;
    sourceError.value = null;
    try {
      const sourceId = String(sourceForm.sourceId || "").trim();
      const exists = Boolean(sourceId && sources.value.some((source) => source.sourceId === sourceId));
      const response = exists ? await projectManagementAPI.updateSource(sourceId, sourceForm) : await projectManagementAPI.createSource(sourceForm);
      if (!response.ok) throw response;
      const savedId = response.data?.source?.sourceId ?? sourceId;
      sourceMessage.value = "Source 已保存";
      await loadNavigationAndSources();
      return savedId;
    } catch (err) {
      sourceError.value = apiErrorOf(err).error;
      return null;
    } finally {
      sourceSaving.value = false;
    }
  }

  async function probeSource(sourceId?: string | null): Promise<void> {
    const id = sourceId || sourceForm.sourceId;
    if (!id) return;
    sourceProbeLoading.value = true;
    sourceMessage.value = null;
    sourceError.value = null;
    try {
      const response = await projectManagementAPI.probeSource(id);
      if (!response.ok) throw response;
      sourceMessage.value = `Probe ${response.data?.probe?.status || "ok"}`;
    } catch (err) {
      sourceError.value = apiErrorOf(err).error;
    } finally {
      sourceProbeLoading.value = false;
    }
  }

  async function reindexSource(sourceId: string): Promise<{ documentCount: number; taskCount: number } | null> {
    sourceReindexLoading.value = true;
    sourceMessage.value = null;
    sourceError.value = null;
    try {
      const response = await projectManagementAPI.reindexSource(sourceId);
      if (!response.ok) throw response;
      const documentCount = response.data?.projection?.documentCount ?? 0;
      const taskCount = response.data?.projection?.taskCount ?? 0;
      sourceMessage.value = `Reindex ${documentCount} files / ${taskCount} tasks`;
      return { documentCount, taskCount };
    } catch (err) {
      sourceError.value = apiErrorOf(err).error;
      return null;
    } finally {
      sourceReindexLoading.value = false;
    }
  }

  function clearSourceMessages(): void {
    sourceMessage.value = null;
    sourceError.value = null;
  }

  return {
    sources,
    navigation,
    sourceForm,
    sourceMessage,
    sourceError,
    sourceSaving,
    sourceProbeLoading,
    sourceReindexLoading,
    loadNavigationAndSources,
    openSourceForm,
    saveSourceConfig,
    probeSource,
    reindexSource,
    clearSourceMessages
  };
}

