// base-api.service.ts
import type { TableState } from "~/components/core/data-table";
import { removeUndefinedValues } from "~/features/remove-falsy-values";
import { mapTableStateToPaginationQueryDSL } from "~/features/table";
import { handleError, handleSuccess } from ".";
import axios from "../lib/axios";
import type { DeepPartial } from "react-hook-form";

export class BaseApiService<T extends { id: number }> {
  constructor(protected readonly resourceUrl: string) {}

  async index(values?: DeepPartial<TableState<T>> | undefined) {
    const params = values
      ? mapTableStateToPaginationQueryDSL(values as TableState<T>)
      : {};

    const response = await axios({
      url: this.resourceUrl,
      params: params,
      // withCredentials: true,
      method: "GET",
    });

    return response.data;
  }

  async get(id: T["id"]) {
    const response = await axios({
      url: this.resourceUrl + "/" + id,
      // withCredentials: true,
      method: "GET",
    });

    return response.data;
  }

  async create(data: Partial<Omit<T, "id" | "created_at" | "updated_at">>) {
    try {
      const newData = removeUndefinedValues(data);
      const { data: result } = await axios({
        url: this.resourceUrl,
        // withCredentials: true,
        method: "POST",
        data: newData,
      });

      handleSuccess(result, this.resourceUrl);
      return result;
    } catch (error) {
      handleError(error);
    }
  }

  async update(id: T["id"], data: Partial<T>) {
    try {
      const cleaned = removeUndefinedValues(data);
      const { data: result } = await axios({
        url: `${this.resourceUrl}/${id}`,
        // withCredentials: true,
        method: "PUT",
        data: cleaned,
      });

      handleSuccess(result, this.resourceUrl);

      return result;
    } catch (error) {
      handleError(error);
    }
  }

  async delete(entity: T) {
    try {
      const { data } = await axios({
        url: `${this.resourceUrl}/${entity.id}`,
        // withCredentials: true,
        method: "DELETE",
      });

      handleSuccess(data, this.resourceUrl);
      return data;
    } catch (error) {
      handleError(error);
    }
  }

  async bulkDelete(entities: T[]) {
    const ids = entities.map((e) => e.id);
    try {
      const { data } = await axios({
        url: `${this.resourceUrl}/bulk-delete`,
        // withCredentials: true,
        method: "DELETE",
        data: { ids },
      });

      handleSuccess(data, this.resourceUrl);

      return data;
    } catch (error) {
      handleError(error);
    }
  }

  async bulkUpdate(entities: T[]) {
    try {
      const { data } = await axios({
        url: `${this.resourceUrl}/bulk-update`,
        // withCredentials: true,
        method: "PUT",
        data: entities,
      });

      handleSuccess(data, this.resourceUrl);

      return data;
    } catch (error) {
      handleError(error);
    }
  }

  // Optional: override this in subclass if needed
  async customAction(
    id: number,
    endpoint: string,
    payload?: Record<string, any>,
    method?: string
  ) {
    try {
      const { data } = await axios({
        url: `${this.resourceUrl}/${endpoint}/${id}`,
        method: method || "POST",
        data: removeUndefinedValues(payload || {}),
        // withCredentials: true,
      });

      handleSuccess(data, this.resourceUrl);
      return data;
    } catch (error) {
      handleError(error);
    }
  }
}
