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,
  isAttachmentCreateMetadata,
  isDeleteDocumentResult,
  isUpdateAttachmentRequest,
  type AttachmentCreateMetadata,
  type BatchImportResult,
  type DeleteDocumentResult,
  type UpdateAttachmentRequest,
} 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 attachmentUploadForm(file: File, metadata: AttachmentCreateMetadata): FormData {
  if (!isAttachmentCreateMetadata(metadata)) throw new Error("附件metadata不符合DMS接口契约");
  const form = new FormData();
  form.append("file", file);
  form.append("metadata", JSON.stringify(metadata));
  return form;
}

export function attachmentBatchImportForm(
  files: File[],
  items: AttachmentCreateMetadata[],
): FormData {
  if (files.length === 0 || files.length !== items.length) {
    throw new Error("files与items数量必须一致且不能为空");
  }
  if (!items.every(isAttachmentCreateMetadata)) {
    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 createAttachmentMutationApi(client: MutationClient = httpClient) {
  return {
    async create(file: File, metadata: AttachmentCreateMetadata, signal?: AbortSignal): Promise<DocumentDetail> {
      const result = await client.post<unknown>(
        "attachments",
        attachmentUploadForm(file, metadata),
        { signal },
      );
      if (!isDocumentDetail(result.data)) throw contractError(result, "附件上传");
      return result.data;
    },

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

    async update(id: string, request: UpdateAttachmentRequest, signal?: AbortSignal): Promise<DocumentDetail> {
      if (!isUpdateAttachmentRequest(request)) throw new Error("附件编辑请求不符合DMS接口契约");
      const result = await client.put<unknown>(`attachments/${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>(`attachments/${id}`, {
        query: { rowVersion },
        signal,
      });
      if (!isDeleteDocumentResult(result.data)) throw contractError(result, "附件删除");
      return result.data;
    },
  };
}

export const attachmentMutationApi = createAttachmentMutationApi();
