import { HttpError } from "../../shared/api/errors";
import { httpClient, type RequestOptions } from "../../shared/api/httpClient";
import type { JsonResult } from "../../shared/api/types";
import { isDocumentDetail, type DocumentDetail } from "../documents/documentTypes";
import {
  isBatchImportResult,
  isDeleteDocumentResult,
  isDocumentCreateMetadata,
  isUpdateDocumentRequest,
  type BatchImportResult,
  type DeleteDocumentResult,
  type DocumentCreateMetadata,
  type DocumentUploadMetadata,
  type UpdateDocumentRequest,
} from "./mutationTypes";

interface MutationClient {
  post<T>(path: string, body?: unknown | FormData, options?: RequestOptions): Promise<JsonResult<T>>;
  put<T>(path: string, body?: unknown | FormData, options?: RequestOptions): Promise<JsonResult<T>>;
  delete<T>(path: string, options?: RequestOptions): Promise<JsonResult<T>>;
}

function contractError(result: JsonResult<unknown>, target: string): HttpError {
  return new HttpError({
    httpStatus: result.httpStatus,
    code: "INTERNAL_ERROR",
    message: `${target}响应不符合DMS接口契约`,
    details: null,
    requestId: result.requestId,
  });
}

export function documentUploadForm(file: File, metadata: DocumentUploadMetadata): FormData {
  if (!isDocumentCreateMetadata(metadata)) throw new Error("文档metadata不符合DMS接口契约");
  const form = new FormData();
  form.append("file", file);
  form.append("metadata", JSON.stringify(metadata));
  return form;
}

export function batchImportForm(
  files: File[],
  items: DocumentCreateMetadata[],
): FormData {
  if (files.length === 0 || files.length !== items.length) {
    throw new Error("files与items数量必须一致且不能为空");
  }
  if (!items.every(isDocumentCreateMetadata)) {
    throw new Error("批量文档metadata不符合DMS接口契约");
  }
  const form = new FormData();
  files.forEach((file) => form.append("files", file));
  form.append("items", JSON.stringify(items));
  return form;
}

export function createDocumentMutationApi(client: MutationClient = httpClient) {
  return {
    async create(file: File, metadata: DocumentUploadMetadata, signal?: AbortSignal): Promise<DocumentDetail> {
      const result = await client.post<unknown>(
        "documents",
        documentUploadForm(file, metadata),
        { signal },
      );
      if (!isDocumentDetail(result.data)) throw contractError(result, "文档上传");
      return result.data;
    },

    async batchImport(files: File[], items: DocumentCreateMetadata[], signal?: AbortSignal): Promise<BatchImportResult> {
      const result = await client.post<unknown>(
        "documents/batch-import",
        batchImportForm(files, items),
        { signal },
      );
      if (!isBatchImportResult(result.data)) throw contractError(result, "方案批量导入");
      return result.data;
    },

    async update(id: string, request: UpdateDocumentRequest, signal?: AbortSignal): Promise<DocumentDetail> {
      if (!isUpdateDocumentRequest(request)) throw new Error("文档编辑请求不符合DMS接口契约");
      const result = await client.put<unknown>(`documents/${id}`, request, { signal });
      if (!isDocumentDetail(result.data)) throw contractError(result, "文档编辑");
      return result.data;
    },

    async remove(id: string, rowVersion: number, signal?: AbortSignal): Promise<DeleteDocumentResult> {
      const result = await client.delete<unknown>(`documents/${id}`, {
        query: { rowVersion },
        signal,
      });
      if (!isDeleteDocumentResult(result.data)) throw contractError(result, "文档删除");
      return result.data;
    },
  };
}

export const documentMutationApi = createDocumentMutationApi();
