import { HttpError } from "../../shared/api/errors";
import {
  httpClient,
  type RequestOptions,
} from "../../shared/api/httpClient";
import type { JsonResult } from "../../shared/api/types";
import {
  isCategoryNode,
  isCategoryTree,
  isDeleteCategoryResult,
  type CategoryNode,
  type CategoryTreeQuery,
  type CreateCategoryRequest,
  type DeleteCategoryResult,
  type UpdateCategoryRequest,
} from "./categoryTypes";

interface CategoryHttpClient {
  get<T>(path: string, options?: RequestOptions): Promise<JsonResult<T>>;
  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>,
  message: string,
): HttpError {
  return new HttpError({
    httpStatus: result.httpStatus,
    code: "INTERNAL_ERROR",
    message,
    details: null,
    requestId: result.requestId,
  });
}

export function createCategoryApi(client: CategoryHttpClient = httpClient) {
  return {
    async getTree(
      query: CategoryTreeQuery = {},
      signal?: AbortSignal,
    ): Promise<CategoryNode[]> {
      const result = await client.get<unknown>("categories/tree", {
        query: {
          keyword: query.keyword,
          status: query.status,
        },
        signal,
      });
      if (!isCategoryTree(result.data)) {
        throw contractError(result, "分类树响应不符合DMS接口契约");
      }
      return result.data;
    },

    async create(request: CreateCategoryRequest): Promise<CategoryNode> {
      const result = await client.post<unknown>("categories", request);
      if (!isCategoryNode(result.data)) {
        throw contractError(result, "新增分类响应不符合DMS接口契约");
      }
      return result.data;
    },

    async update(
      id: string,
      request: UpdateCategoryRequest,
    ): Promise<CategoryNode> {
      const result = await client.put<unknown>(`categories/${id}`, request);
      if (!isCategoryNode(result.data)) {
        throw contractError(result, "编辑分类响应不符合DMS接口契约");
      }
      return result.data;
    },

    async remove(id: string, rowVersion: number): Promise<DeleteCategoryResult> {
      const result = await client.delete<unknown>(`categories/${id}`, {
        query: { rowVersion },
      });
      if (!isDeleteCategoryResult(result.data)) {
        throw contractError(result, "删除分类响应不符合DMS接口契约");
      }
      return result.data;
    },
  };
}

export const categoryApi = createCategoryApi();
export type CategoryApi = ReturnType<typeof createCategoryApi>;
