import { HttpError } from "../../shared/api/errors";
import { httpClient, type RequestOptions } from "../../shared/api/httpClient";
import type { JsonResult, PageResult } from "../../shared/api/types";
import {
  isRecycleBinPage,
  isRestoreDocumentRequest,
  isRestoreDocumentResult,
  type RecycleBinDocumentSummary,
  type RecycleBinQuery,
  type RestoreDocumentRequest,
  type RestoreDocumentResult,
} from "./recycleBinTypes";

interface RecycleBinHttpClient {
  get<T>(path: string, options?: RequestOptions): Promise<JsonResult<T>>;
  post<T>(
    path: string,
    body?: unknown,
    options?: RequestOptions,
  ): Promise<JsonResult<T>>;
}

export interface RestoreResultEnvelope {
  data: RestoreDocumentResult;
  requestId: string;
}

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,
  });
}

function assertId(id: unknown): asserts id is string {
  if (typeof id !== "string" || !/^[0-9]+$/.test(id)) {
    throw new TypeError("回收站文档ID必须是十进制字符串");
  }
}

export function createRecycleBinApi(
  client: RecycleBinHttpClient = httpClient,
) {
  return {
    async list(
      query: RecycleBinQuery,
      signal?: AbortSignal,
    ): Promise<PageResult<RecycleBinDocumentSummary>> {
      const result = await client.get<unknown>("recycle-bin/documents", {
        query: { ...query },
        signal,
      });
      if (!isRecycleBinPage(result.data)) {
        throw contractError(result, "回收站列表");
      }
      return result.data;
    },

    async restore(
      id: string,
      request: RestoreDocumentRequest,
      signal?: AbortSignal,
    ): Promise<RestoreResultEnvelope> {
      assertId(id);
      if (!isRestoreDocumentRequest(request)) {
        throw new TypeError("恢复请求不符合DMS接口契约");
      }
      const result = await client.post<unknown>(
        `recycle-bin/documents/${id}/restore`,
        request,
        { signal },
      );
      if (!isRestoreDocumentResult(result.data)) {
        throw contractError(result, "文档恢复");
      }
      return { data: result.data, requestId: result.requestId };
    },
  };
}

export const recycleBinApi = createRecycleBinApi();
export type RecycleBinApi = ReturnType<typeof createRecycleBinApi>;

