import { AxiosResponse } from "axios";
import axiosInstance from "./axiosInstance";

export type AddReferenceNumberPayload = {
  referenceNumberPrefix?: { am: string; en: string };
  externalReferenceNumberPrefix?: { am: string; en: string };
  internalMemoReferenceNumberPrefix?: { am: string; en: string };
};

export type UpdateInternalMemoPrefixPayload = {
  referenceNumberPrefix?: { am: string; en: string };
  externalReferenceNumberPrefix?: { am: string; en: string };
  internalMemoReferenceNumberPrefix?: { am: string; en: string };
};

export type UpdateExternalReferencePrefixPayload = {
  referenceNumberPrefix?: { am: string; en: string };
  externalReferenceNumberPrefix?: { am: string; en: string };
  internalMemoReferenceNumberPrefix?: { am: string; en: string };
};

export type DeleteReferenceNumberPayload = {
  recordSequenceTypes: string[];
};

// sequence-count.dto.ts

export enum SequenceType {
  EXTERNAL_REFERENCE_NUMBER = "externalReferenceNumberPrefix",
  INTERNAL_MEMO_REFERENCE_NUMBER = "internalMemoReferenceNumberPrefix",
  REFERENCE_NUMBER = "referenceNumberPrefix",
}

export interface ReferenceNumbersResponse {
  id?: string;
  name: SequenceType;
  number: {
    am: string | { am: string };
    en?: string | { am: string };
  };
  sequenceId: string;
  count: number;
}

export interface UnitConfigurationResponse extends ReferenceNumbersResponse {
  id?: string;
  unitId?: string;
  [key: string]: unknown;
}

export interface CanReceiveComplaintResponse {
  canReceiveComplaint: boolean;
  unitId?: string;
  unitName?: string;
}

const errorMessage = (error: unknown, fallback: string) => {
  const err = error as {
    response?: { data?: { message?: string } };
    message?: string;
  };
  return err?.response?.data?.message || err?.message || fallback;
};

const isUnitNotFoundError = (error: unknown) => {
  const err = error as {
    response?: { status?: number; data?: { message?: string } };
    message?: string;
  };
  const message = err?.response?.data?.message || err?.message || "";
  return err?.response?.status === 400 && /unit not found/i.test(message);
};

const createAxiosResponse = <T>(data: T): AxiosResponse<T> => ({
  data,
  status: 200,
  statusText: "OK",
  headers: {},
  config: {} as any,
});

export const unitConfigurationService = {
  getReferenceNumbers: async (
    unitId: string,
  ): Promise<AxiosResponse<ReferenceNumbersResponse[]>> => {
    try {
      return await axiosInstance.get(
        `/unit-configurations/${unitId}/reference-number`,
      );
    } catch (error) {
      if (isUnitNotFoundError(error)) {
        return createAxiosResponse<ReferenceNumbersResponse[]>([]);
      }
      throw new Error(errorMessage(error, "Failed to fetch reference numbers"));
    }
  },
  getTagBasedReferences: async (
    unitId: string,
    tagId?: string,
  ): Promise<AxiosResponse<ReferenceNumbersResponse[]>> => {
    try {
      return await axiosInstance.get(`/record-prefixes/list/${unitId}/`);
    } catch (error) {
      if (isUnitNotFoundError(error)) {
        return createAxiosResponse<ReferenceNumbersResponse[]>([]);
      }
      throw new Error(errorMessage(error, "Failed to fetch reference numbers"));
    }
  },

  getUnitConfiguration: async (
    unitId: string,
  ): Promise<AxiosResponse<UnitConfigurationResponse>> => {
    try {
      return await axiosInstance.get(`/unit-configurations/${unitId}`);
    } catch (error) {
      throw new Error(
        errorMessage(error, "Failed to fetch unit configuration"),
      );
    }
  },

  addReferenceNumber: async (
    unitId: string,
    payload: AddReferenceNumberPayload,
  ): Promise<AxiosResponse<ReferenceNumbersResponse>> => {
    try {
      return await axiosInstance.post(
        `/unit-configurations/${unitId}/reference-number`,
        payload,
      );
    } catch (error) {
      if (isUnitNotFoundError(error)) {
        await axiosInstance.post(`/unit-configurations`, { unitId });
        return await axiosInstance.post(
          `/unit-configurations/${unitId}/reference-number`,
          payload,
        );
      }
      throw new Error(errorMessage(error, "Failed to add reference numbers"));
    }
  },

  deleteReferenceNumber: async (
    id: string,
    payload: DeleteReferenceNumberPayload,
  ): Promise<AxiosResponse<void>> => {
    try {
      return await axiosInstance.delete(`/unit-configurations/${id}/reference-number`, {
        data: payload,
      });
    } catch (error) {
      throw new Error(errorMessage(error, "Failed to delete reference number"));
    }
  },

  updateInternalMemoReferencePrefix: async (
    unitId: string,
    payload: UpdateInternalMemoPrefixPayload,
  ): Promise<AxiosResponse<ReferenceNumbersResponse>> => {
    try {
      return await axiosInstance.patch(
        `/unit-configurations/add-internal-memo-reference-number-prefix/${unitId}`,
        payload,
      );
    } catch (error) {
      if (isUnitNotFoundError(error)) {
        await axiosInstance.post(`/unit-configurations`, { unitId });
        return await axiosInstance.patch(
          `/unit-configurations/add-internal-memo-reference-number-prefix/${unitId}`,
          payload,
        );
      }
      throw new Error(
        errorMessage(error, "Failed to update internal memo reference prefix"),
      );
    }
  },

  updateExternalReferencePrefix: async (
    unitId: string,
    payload: UpdateExternalReferencePrefixPayload,
  ): Promise<AxiosResponse<ReferenceNumbersResponse>> => {
    try {
      return await axiosInstance.patch(
        `/unit-configurations/add-external-reference-number-prefix/${unitId}`,
        payload,
      );
    } catch (error) {
      if (isUnitNotFoundError(error)) {
        await axiosInstance.post(`/unit-configurations`, { unitId });
        return await axiosInstance.patch(
          `/unit-configurations/add-external-reference-number-prefix/${unitId}`,
          payload,
        );
      }
      throw new Error(
        errorMessage(error, "Failed to update external reference prefix"),
      );
    }
  },

  // Whether the given unit can receive complaints.
  getCanReceiveComplaint: async (
    unitId: string,
  ): Promise<AxiosResponse<CanReceiveComplaintResponse>> => {
    if (!unitId?.trim()) {
      throw new Error("Unit ID is required to check complaint receiving.");
    }

    return axiosInstance.get(`/unit-configurations/can-receive-complaint`, {
      params: { unitId },
    });
  },
};
