import { HttpError } from "../../shared/api/errors";
import { httpClient, type RequestOptions } from "../../shared/api/httpClient";
import type { JsonResult, PageResult } from "../../shared/api/types";
import {
  isDocumentDetail,
  isDocumentSummary,
  isPageResult,
  type DocumentDetail,
  type DocumentListQuery,
  type DocumentSummary,
  type SubPlanListQuery,
} from "./documentTypes";

interface DocumentHttpClient {
  get<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 createDocumentApi(client: DocumentHttpClient = httpClient) {
  return {
    async list(
      query: DocumentListQuery,
      signal?: AbortSignal,
    ): Promise<PageResult<DocumentSummary>> {
      const result = await client.get<unknown>("documents", {
        query: { ...query },
        signal,
      });
      if (!isPageResult(result.data, isDocumentSummary)) {
        throw contractError(result, "文档列表");
      }
      return result.data;
    },

    async detail(id: string, signal?: AbortSignal): Promise<DocumentDetail> {
      const result = await client.get<unknown>(`documents/${id}`, { signal });
      if (!isDocumentDetail(result.data)) {
        throw contractError(result, "文档详情");
      }
      return result.data;
    },

    async subPlans(
      mainPlanId: string,
      query: SubPlanListQuery,
      signal?: AbortSignal,
    ): Promise<PageResult<DocumentSummary>> {
      const result = await client.get<unknown>(
        `main-plans/${mainPlanId}/sub-plans`,
        { query: { ...query }, signal },
      );
      if (!isPageResult(result.data, isDocumentSummary)) {
        throw contractError(result, "直属子方案列表");
      }
      return result.data;
    },

    async listTags(signal?: AbortSignal): Promise<string[]> {
      const result = await client.get<unknown>("documents/tags", { signal });
      const payload = result.data as { items?: unknown; total?: unknown } | null;
      if (
        !payload ||
        typeof payload !== "object" ||
        !Array.isArray((payload as { items?: unknown }).items) ||
        !(payload as { items: unknown[] }).items.every(
          (item) => typeof item === "string",
        )
      ) {
        throw contractError(result, "主案标签");
      }
      return (payload as { items: string[] }).items;
    },
  };
}

export const documentApi = createDocumentApi();
export type DocumentApi = ReturnType<typeof createDocumentApi>;
