// SPEC: PJ2026-01040409 MDTODO前端重写; draft-2026-06-26-p0-mdtodo-web-rewrite.
// Responsibility: task create/update/delete via public API with revision/fingerprint concurrency protection.

import { ref } from "vue";
import {
  projectManagementAPI,
  type MdtodoTaskMutationInput,
  type MdtodoTaskRecord,
} from "@/api";
import type { ApiError, ErrorDiagnostic } from "@/types";

function mutationErrorOf(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 || "任务操作失败"),
    apiError: null,
    diagnostic: null,
  };
}

/**
 * All task mutations go through the public Project Management API and carry an
 * expectedFingerprint/revision for optimistic-concurrency protection. The frontend
 * may optimistic-update, but on API failure, version conflict, parse error or
 * HWPOD offline it must roll back or surface a recoverable error. The frontend
 * never edits Markdown files directly or persists to localStorage.
 */
export function useMdtodoTaskMutation() {
  const taskMutationLoading = ref(false);
  const taskMutationError = ref<string | null>(null);
  const taskMutationMessage = ref<string | null>(null);

  function clearMessages(): void {
    taskMutationError.value = null;
    taskMutationMessage.value = null;
  }

  /**
   * Run a mutation action, then refresh the caller-provided reload function and
   * return the resulting taskRef so the caller can reselect. On conflict/failure
   * the error is surfaced and the caller decides whether to roll back the local
   * edit draft.
   */
  async function runTaskMutation(
    action: () => ReturnType<typeof projectManagementAPI.updateTask>,
    preferredTaskRef: string | undefined,
    message: string,
    onAfterMutate: () => Promise<void>,
  ): Promise<string | null> {
    taskMutationLoading.value = true;
    taskMutationError.value = null;
    taskMutationMessage.value = null;
    try {
      const response = await action();
      if (!response.ok) throw response;
      const nextTaskRef =
        response.data?.task?.taskRef || preferredTaskRef || null;
      await onAfterMutate();
      taskMutationMessage.value = message;
      return nextTaskRef;
    } catch (err) {
      taskMutationError.value = mutationErrorOf(err).error;
      return null;
    } finally {
      taskMutationLoading.value = false;
    }
  }

  async function updateTask(
    taskRef: string,
    input: MdtodoTaskMutationInput,
    message: string,
    onAfterMutate: () => Promise<void>,
  ): Promise<string | null> {
    return runTaskMutation(
      () => projectManagementAPI.updateTask(taskRef, input),
      taskRef,
      message,
      onAfterMutate,
    );
  }

  async function createTask(
    input: MdtodoTaskMutationInput,
    message: string,
    onAfterMutate: () => Promise<void>,
  ): Promise<string | null> {
    return runTaskMutation(
      () => projectManagementAPI.createTask(input),
      undefined,
      message,
      onAfterMutate,
    );
  }

  async function deleteTask(
    taskRef: string,
    input: MdtodoTaskMutationInput,
    onAfterMutate: () => Promise<void>,
  ): Promise<string | null> {
    return runTaskMutation(
      () => projectManagementAPI.deleteTask(taskRef, input),
      taskRef,
      "任务已删除",
      onAfterMutate,
    );
  }

  return {
    taskMutationLoading,
    taskMutationError,
    taskMutationMessage,
    clearMessages,
    runTaskMutation,
    updateTask,
    createTask,
    deleteTask,
  };
}
