import {
  PodcastValidateParams,
  PodcastSyncLatestParams,
  RequestTalentProfileRequest,
} from "./../../types";
import {
  ExportDataFormRequest,
  getDataFormCountResult,
} from "./../../redux/User/types";
import { ApiResponse, ApisauceInstance, create } from "apisauce";
import { CancelToken } from "axios";
import Cookies from "js-cookie";
import pRetry from "p-retry";

import {
  CreateAvailablePeriodRequest,
  GetAvailablePeriodRequest,
  GetAvailablePeriodResponse,
} from "models/availability-calendar/availability-calendar.model";
import {
  CancelInviteCollaboratorRequest,
  InviteCollaboratorRequest,
  ResendInviteCollaboratorRequest,
  RevokeInviteCollaboratorRequest,
} from "models/talent/talent-profile-collaborator.model";
import {
  CreateTalentProfileModuleRequest,
  ReorderTalentProfileModuleRequest,
  ReorderShopifyStoreRequest,
  TalentModuleMixItem,
  TalentProfileModule,
  UpdateTalentProfileModuleRequest,
  publishProfileRequest,
  DeleteLocalizationRequest,
  autoSaveProfileRequest,
  requestOTPRequest,
  TFAVerificationRequest,
} from "models/talent/talent-profile-module.model";
import {
  CreateAvailabilityRule,
  UpdateAvailabilityRule,
} from "redux/Availability/types";
import {
  Booking,
  CompleteBookingRequest,
  GetBookingDetailRequest,
  GetBookingRequest,
  RejectBookingRequest,
  UpdateBookingAttachmentsRequest,
} from "redux/Booking/types";
import { Category } from "redux/Category/types";
import { OkResponse, Response } from "redux/Common/types";
import {
  Contents1To1Request,
  EXPERIENCE_STATUS,
  EXPERIENCE_TYPE,
  UpdateExperience1To1Request,
  UpdateExperienceRequest,
} from "redux/Experience/types";
import { AddPayoutMethodRequest, PayoutSchedule } from "redux/Payout/types";
import { Product, ProductRequest } from "redux/Product/types";
import { CreatePurchasingOptionsRequest } from "redux/PurchasingOptions/types";
import { RoomToken } from "redux/Room/types";
import {
  ExperienceSchduled,
  GetExperiencesScheduled,
} from "redux/ExperiencesScheduled/types";
import { GetSpecialRequests, SpecialRequest } from "redux/SpecialRequest/types";
import {
  Analytics,
  DataForm,
  FinishTalentProfileRequest,
  GetAnalyticRequest,
  TalentProfileRequest,
  VerifyBecomeTalentOtpRequest,
} from "redux/Talent/types";
import {
  CopyTimeRangeRequest,
  CreateDateOffRequest,
  CreateTimeRangeRequest,
  DeleteDateOffRequest,
  DeleteTimeRangeRequest,
  DeleteWeekDayRequest,
  RepeatTimeRangeRequest,
  UpdateTimeRangeRequest,
} from "redux/TimeRange/types";
import {
  CALENDAR_PROVIDERS,
  CheckUserExistedRequest,
  CheckUserExistedResult,
  ExchangeRate,
  ExportFanClubRequest,
  getFanClubCountResult,
  PhoneOTP,
  SendEmailOTPRequest,
  SendPhoneOTPRequest,
  SpotifyConnectRequest,
  SpotifyConnectResponse,
  SpotifyUser,
  StripeConnectRequest,
  StripeConnectResponse,
  UpdatePasswordRequest,
  User,
} from "redux/User/types";
import { KOMI_TALENT_CURRENCY } from "services/UserService";
import { ListQueryParams, Pagination } from "../../redux/Common/types";
import {
  Experience,
  GetExperienceByIdRequest,
} from "../../redux/Experience/types";
import { PurchasingOptions } from "../../redux/PurchasingOptions/types";
import { ApiConfig, DEFAULT_API_CONFIG } from "./api.config";
import { getGeneralApiProblem } from "./apiProblem";
import { DspLinkPayload, DspResource } from "types/dsp";
import { YoutubeParams, YoutubeResponse } from "types/youtube";
import { MetaPixelParams } from "types";
import { getCorrelationId, getSessionId } from "@komi-app/correlation";
import {
  CanDeletePaymentMethodSuccess,
  CustomerWithDetailsSuccess,
  Interval,
  ProductKey,
  ProductSuccess,
  SalesSuccess,
  StripeSetupIntentSuccess,
  SubscriptionSuccess,
} from "types/sales";
import { CancelFeedback } from "@komi-app/components";
import config from "config";
import {
  CampaignReportResponse,
  CampaignResponse,
  CampaignsResponse,
  CampaignsWithCursorResponse,
  CampaignUpsertDto,
  CheckNameExistsResponse,
} from "types/campaigns";
import {
  Segment,
  GetSegmentResponse,
  GetAllSegments,
  CreateSegmentResponse,
  DeleteSegmentResponse,
  GetAllSegmentsPaginated,
  GetGeoCitiesResponse,
  GetGeoCountriesResponse,
  GetGeoStatesResponse,
  UpdateSegmentResponse,
  MarketingPermission,
  FanSubmission,
} from "@komi-app/fans-sdk";
import { DeepPartial } from "types/utilities";
import {
  FEATURE_LIST_HEADER,
  FEATURE_LIST_LOCAL_STORAGE,
} from "constants/feature-flags";
import {
  LinkRedirectDto,
  LinkRedirectResponse,
  LinkRedirectUpdateStatusDto,
} from "types/linkRedirects";
import {
  CampaignTemplateCreateDto,
  CampaignTemplateResponse,
  TemplateDto,
  TemplateResponse,
  TemplateSignedUrlResponse,
  TemplatesResponse,
  TemplatesWithCursorResponse,
} from "types/templates";
import {
  FanTableSchema,
  FanWithCursorResponseSchema,
} from "pages/AudienceAndCampaigns/Pages/Contacts/Utils";
import {
  PatchEmailDomainRequest,
  PostEmailDomainRequest,
  GetEmailDomainResponse,
  PostSendTestEmailRequest,
} from "types/email-domains";
import { CountQueryResponse } from "types/query";
import { string } from "yup";
import { KOMI_CSRF } from "services/AuthService";
import { TALENT_PROFILE_ID } from "constants/profile";
import { OneSchemaSuccessEvent } from "pages/AudienceAndCampaigns/Pages/Contacts/Types";
import {
  CountQueryParameters,
  PaginationQueryParameters,
} from "hooks/usePagination";

import { REFRESH_STATUS_CODE } from "@komi-app/sdk";
import { FLAGS, isOn } from "@komi-app/flags-sdk";
import { DigitalProductUploadBody, DigitalProductUploadTokenResponse } from "@komi-app/profiles-sdk";

export class Api {
  /**
   * The underlying apisauce instance which performs the requests.
   */
  apisauceSecure: ApisauceInstance;

  /**
   * Configurable options.
   */
  config: ApiConfig;

  /**
   * Profile Id used by profile service
   */
  profileId: string;

  /**
   * Creates the api.
   *
   * @param config The configuration to use.
   */
  constructor(config: ApiConfig = DEFAULT_API_CONFIG) {
    this.config = config;
    this.profileId = "";
    this.apisauceSecure = create({
      baseURL: this.config.url,
      timeout: this.config.timeout,
      headers: {
        Accept: "application/json",
      },
      withCredentials: true,
    });
  }

  /**
   * Get instance of apisauceSecure.
   */
  get instanceSecure(): ApisauceInstance {
    return this.apisauceSecure;
  }

  /**
   * Sets up the API.  This will be called during the bootup
   * sequence and will happen before the first React component
   * is mounted.
   *
   * Be as quick as possible in here.
   */
  setup() {
    this.apisauceSecure.axiosInstance.interceptors.request.use(
      async (options) => {
        const headers: Record<string, string> = {};

        // TODO: Implement auto refresh token here

        const currencyCode = Cookies.get(KOMI_TALENT_CURRENCY);
        const correlationId = getCorrelationId();
        const sessionId = getSessionId();
        const serviceName = config.service.name || "";
        const serviceVersion = config.service.version || "";
        const featureList = localStorage.getItem(FEATURE_LIST_LOCAL_STORAGE);
        const csrfToken = Cookies.get(KOMI_CSRF);
        const talentProfileId =
          this.profileId || Cookies.get(TALENT_PROFILE_ID);

        if (currencyCode) {
          headers["local-currency-code"] = currencyCode;
        }

        if (correlationId) {
          headers["x-correlation-id"] = correlationId;
        }
        if (sessionId) {
          headers["x-session-id"] = sessionId;
        }
        if (serviceName) {
          headers["x-service-name"] = serviceName;
        }
        if (serviceVersion) {
          headers["x-service-version"] = serviceVersion;
        }
        if (csrfToken) {
          headers["x-komi-csrf"] = csrfToken;
        }
        if (featureList) {
          headers[FEATURE_LIST_HEADER] = featureList;
        }
        if (talentProfileId) {
          headers["x-profile-id"] = talentProfileId;
        }

        options.headers = { ...options.headers, ...headers };

        return options;
      },
      (error) => {
        // Do something with request error
        return Promise.reject(error);
      },
    );
  }

  setProfileId(profileId: string): void {
    this.profileId = profileId;
    // dirty fix
    Cookies.set(TALENT_PROFILE_ID, profileId);
  }

  private requestAPI<P, R>(
    url: string,
    method: "get" | "delete" | "delete-payload" | "put" | "post" | "patch",
    cancelToken?: CancelToken,
  ) {
    return async (payload?: P): Promise<Response<R>> => {
      let response: ApiResponse<any>;
      let call: () => Promise<ApiResponse<any>>;

      switch (method) {
        case "get":
          call = () =>
            this.apisauceSecure.get(url, payload as {}, {
              cancelToken,
            });
          break;
        case "post":
          call = () => this.apisauceSecure.post(url, payload);
          break;
        case "put":
          call = () => this.apisauceSecure.put(url, payload);
          break;
        case "delete":
          call = () => this.apisauceSecure.delete(url, payload as {});
          break;
        case "delete-payload":
          call = () => this.apisauceSecure.delete(url, {}, { data: payload });
          break;
        case "patch":
          call = () => this.apisauceSecure.patch(url, payload);
          break;
        default:
          call = () => this.apisauceSecure.get(url, payload as {});
      }

      response = await call();

      const useLegacyAuthApi = isOn(FLAGS.USE_LEGACY_AUTH_API);

      if (!useLegacyAuthApi && response.status === REFRESH_STATUS_CODE) {
        await this.apisauceSecure.post(
          `${config.auth.url}/v1/refresh`,
          {},
          {
            data: {},
          },
        );

        response = await call();
      }

      if (!response.ok) {
        return getGeneralApiProblem(response);
      }

      return { ok: response.ok, response: response.data };
    };
  }
  async postRequest<P = any | undefined, R = any>(
    url: string,
    payload?: P,
  ): Promise<Response<R>> {
    return this.requestAPI<P, R>(url, "post")(payload);
  }

  getRequest = async <P, R = any>(
    url: string,
    payload?: P,
    cancelToken?: CancelToken,
  ): Promise<Response<R>> => {
    return this.requestAPI<P, R>(url, "get", cancelToken)(payload);
  };

  async putRequest<P, R = any>(url: string, payload?: P): Promise<Response<R>> {
    return this.requestAPI<P, R>(url, "put")(payload);
  }

  async patchRequest<P, R = any>(
    url: string,
    payload?: P,
  ): Promise<Response<R>> {
    return this.requestAPI<P, R>(url, "patch")(payload);
  }

  async deleteRequest<P, R = any>(
    url: string,
    payload?: P,
  ): Promise<Response<R>> {
    return this.requestAPI<P, R>(url, "delete")(payload);
  }

  deleteRequestWithPayload<P, R = any>(
    url: string,
    payload?: P,
  ): Promise<Response<R>> {
    return this.requestAPI<P, R>(url, "delete-payload")(payload);
  }

  async retryRequest<T>(
    requestFn: () => Promise<Response<T>>,
    retries = 10,
  ): Promise<Response<T>> {
    return pRetry(
      async () => {
        const res = await requestFn();

        if (!res) {
          throw new Error("Request failed");
        }
        if (!("ok" in res)) {
          throw new Error("Request failed");
        }

        return res;
      },
      {
        retries,
      },
    );
  }

  removeAuthToken(): void {
    this.apisauceSecure.deleteHeader("Authorization");
  }

  async logout(): Promise<Response<boolean>> {
    return this.postRequest("/auth/logout");
  }

  async getUserProfile(): Promise<Response<User>> {
    const getResponse = await this.getRequest<never, User>(`users/me`);
    if (getResponse && Api.isOKResponse(getResponse)) {
      const { talentProfile } = getResponse.response;
      if (talentProfile?.id) {
        //Set profile id
        this.setProfileId(talentProfile.id);
      }
    }
    return getResponse;
  }

  static isOKResponse<T>(response: Response<T>): response is OkResponse<T> {
    return !!response && "ok" in response;
  }

  async updateConsumerProfile(payload: User): Promise<Response<User>> {
    return this.patchRequest(`/users/me/talent-profiles`, payload);
  }

  async getAllExperiences(
    params: ListQueryParams,
  ): Promise<Response<Experience[]>> {
    return this.getRequest<ListQueryParams>(`users/me/experiences`, {
      ...params,
    });
  }

  async getExperiences(
    type: EXPERIENCE_TYPE,
    userId: string,
    params: ListQueryParams,
  ): Promise<Response<Experience[]>> {
    return this.getRequest<ListQueryParams & { type: EXPERIENCE_TYPE[] }>(
      `users/me/experiences`,
      {
        ...params,
        type: Array.isArray(type) ? type : [type],
      },
    );
  }

  async getExperiencesScheduled(
    payload: GetExperiencesScheduled,
    cancelToken?: CancelToken,
  ): Promise<Response<ExperienceSchduled[]>> {
    return this.getRequest<GetExperiencesScheduled>(
      `/experiences/scheduled`,
      payload,
      cancelToken,
    );
  }

  async getExperienceById(
    payload: GetExperienceByIdRequest,
  ): Promise<Response<Experience>> {
    return this.getRequest<GetExperienceByIdRequest>(
      `/experiences/${payload.expId}`,
      undefined,
      payload.cancelToken,
    );
  }

  async createExperience1To1(
    payload: Contents1To1Request,
  ): Promise<Response<Experience>> {
    return this.postRequest<Contents1To1Request>(
      "/experiences/one-to-one-tutorials",
      payload,
    );
  }

  async updateExperience1To1(
    payload: UpdateExperience1To1Request,
  ): Promise<Response<Experience>> {
    return this.patchRequest<Contents1To1Request>(
      `/experiences/one-to-one-tutorials/${payload.id}`,
      payload.requestBody,
    );
  }

  async updateExperience(
    payload: UpdateExperienceRequest,
  ): Promise<Response<Experience>> {
    return this.putRequest<{ status: EXPERIENCE_STATUS }>(
      `/experiences/${payload.id}`,
      payload.requestBody,
    );
  }

  async publishExperience1To1(payload: string): Promise<Response<any>> {
    return this.patchRequest<Contents1To1Request>(
      `/experiences/${payload}/publish`,
    );
  }

  async createCourse(
    payload: Contents1To1Request,
  ): Promise<Response<Experience>> {
    return this.postRequest<Contents1To1Request>(
      "/experiences/courses",
      payload,
    );
  }

  async updateCourse(
    payload: UpdateExperience1To1Request,
  ): Promise<Response<Experience>> {
    return this.patchRequest<Contents1To1Request>(
      `/experiences/courses/${payload.id}`,
      payload.requestBody,
    );
  }

  async publishCourse(payload: string): Promise<Response<any>> {
    return this.patchRequest<Contents1To1Request>(
      `/experiences/${payload}/publish`,
    );
  }

  async createExperienceLiveClass(
    payload: Contents1To1Request,
  ): Promise<Response<Experience>> {
    return this.postRequest<Contents1To1Request>(
      "/experiences/live-classes",
      payload,
    );
  }

  async updateExperienceLiveClass(
    payload: UpdateExperience1To1Request,
  ): Promise<Response<Experience>> {
    return this.patchRequest<Contents1To1Request>(
      `/experiences/live-classes/${payload.id}`,
      payload.requestBody,
    );
  }

  async publishExperienceLiveClass(payload: string): Promise<Response<any>> {
    return this.patchRequest<Contents1To1Request>(
      `/experiences/${payload}/publish`,
    );
  }

  async createExperienceBundle(
    payload: Contents1To1Request,
  ): Promise<Response<Experience>> {
    return this.postRequest<Contents1To1Request>(
      "/experiences/bundles",
      payload,
    );
  }

  async updateExperienceBundle(
    payload: UpdateExperience1To1Request,
  ): Promise<Response<Experience>> {
    return this.patchRequest<Contents1To1Request>(
      `/experiences/bundles/${payload.id}`,
      payload.requestBody,
    );
  }

  async publishExperienceBundle(payload: string): Promise<Response<any>> {
    return this.patchRequest<Contents1To1Request>(
      `/experiences/${payload}/publish`,
    );
  }

  async deleteExperienceBundle(
    bundleId: string,
    experienceId: string,
  ): Promise<Response<any>> {
    return this.deleteRequest(
      `/experiences/bundles/${bundleId}/experience/${experienceId}`,
    );
  }

  async createExclusiveContent(
    payload: Contents1To1Request,
  ): Promise<Response<Experience>> {
    return this.postRequest<Contents1To1Request>(
      "/experiences/exclusive-contents",
      payload,
    );
  }

  async updateExclusiveContent(
    payload: UpdateExperience1To1Request,
  ): Promise<Response<Experience>> {
    return this.patchRequest<Contents1To1Request>(
      `/experiences/exclusive-contents/${payload.id}`,
      payload.requestBody,
    );
  }

  async publishExclusiveContent(payload: string): Promise<Response<any>> {
    return this.patchRequest<Contents1To1Request>(
      `/experiences/${payload}/publish`,
    );
  }

  async createPurchasingOptions(
    payload: CreatePurchasingOptionsRequest,
  ): Promise<Response<PurchasingOptions>> {
    return this.postRequest<CreatePurchasingOptionsRequest>(
      "/purchase-options",
      payload,
    );
  }

  async getPurchasingOptions(
    params: ListQueryParams,
  ): Promise<Response<Pagination<PurchasingOptions[]>>> {
    return this.getRequest<ListQueryParams>("/purchase-options", params);
  }

  async updatePurchasingOptions(
    payload: any,
  ): Promise<Response<PurchasingOptions>> {
    return this.patchRequest<any>("/purchase-options", payload);
  }

  async getPurchasingOptionsById(
    id: string,
  ): Promise<Response<Pagination<PurchasingOptions>>> {
    return this.getRequest(`/purchase-options/${id}`);
  }

  async getBookings1To1(
    payload: GetBookingRequest,
  ): Promise<Response<Pagination<Booking[]>>> {
    return this.getRequest<ListQueryParams>(
      `users/${payload.userId}/bookings`,
      payload.params,
    );
  }

  async getBooking1To1ById(
    payload: GetBookingDetailRequest,
  ): Promise<Response<Booking>> {
    return this.getRequest(`/bookings/${payload.bookingId}`);
  }

  updateBookingAttachments = (
    payload: UpdateBookingAttachmentsRequest,
  ): Promise<Response<string[]>> => {
    return this.postRequest(`/bookings/${payload.id}/attachments`, {
      urls: payload.urls,
    });
  };

  async rejectBooking(
    payload: RejectBookingRequest,
  ): Promise<Response<Booking>> {
    const { bookingId, notes } = payload;

    return this.postRequest(`bookings/${bookingId}/reject`, { notes });
  }

  async completeBooking(
    payload: CompleteBookingRequest,
  ): Promise<Response<Booking>> {
    const { bookingId, notes } = payload;

    return this.postRequest(`bookings/${bookingId}/complete`, { notes });
  }

  async completeRoom(roomId: number): Promise<Response<Booking>> {
    return this.postRequest(`/rooms/${roomId}/complete`);
  }

  async getRoomToken(bookingId: number): Promise<Response<RoomToken>> {
    return this.postRequest<{ bookingId: number }>(
      "/rooms/one-to-one-tutorial/access-token",
      {
        bookingId,
      },
    );
  }

  async getLiveClassRoomToken(bookingId: number): Promise<Response<RoomToken>> {
    return this.postRequest<{ bookingId: number }>(
      "/rooms/live-class/access-token",
      {
        bookingId,
      },
    );
  }

  async getRoomViewers(roomId: number): Promise<Response<User[]>> {
    return this.getRequest<{ roomId: number }>(`/rooms/${roomId}/participants`);
  }

  async createPresignedPhotoUrl(
    fileExtension: string,
    contentType: string,
  ): Promise<Response<any>> {
    return this.postRequest<{ fileExtension: string; contentType: string }>(
      `/files/photos/presigned-url`,
      { fileExtension, contentType },
    );
  }
  async createPresignedVideoUrl(fileExtension: string): Promise<Response<any>> {
    return this.postRequest<{ fileExtension: string }>(
      `/files/videos/presigned-url`,
      { fileExtension },
    );
  }

  async createPresignedUrl(
    fileExtension: string,
    fileName: string,
    contentType: string,
  ): Promise<Response<any>> {
    return this.postRequest<{
      fileExtension: string;
      fileName: string;
      contentType: string;
    }>(`/files/presigned-url`, {
      fileExtension,
      fileName,
      contentType,
    });
  }

  async createInitiateMultipartUpload(
    fileExtension: string,
    fileName: string,
    fileSize: number,
  ): Promise<Response<any>> {
    return this.postRequest<{
      fileExtension: string;
      fileName: string;
      fileSize: number;
    }>(`/files/videos/initiate-multipart-upload`, {
      fileExtension,
      fileName,
      fileSize,
    });
  }

  async getCompleteMultipartUpload(
    objectKey: string,
    uploadId: string,
    parts: Array<{ ETag: string; PartNumber: number }>,
  ): Promise<Response<any>> {
    return this.postRequest<{
      objectKey: string;
      uploadId: string;
      parts: Array<{ ETag: string; PartNumber: number }>;
    }>(`/files/videos/complete-multipart-upload`, {
      objectKey,
      uploadId,
      parts,
    });
  }

  async stopMultipartUpload(
    objectKey: string,
    uploadId: string,
  ): Promise<Response<any>> {
    return this.postRequest<{
      objectKey: string;
      uploadId: string;
    }>(`/files/videos/stop-multipart-upload`, {
      objectKey,
      uploadId,
    });
  }

  async createTimeRange(
    payload: CreateTimeRangeRequest,
  ): Promise<Response<any>> {
    const { expId, ...rest } = payload;
    return this.postRequest(`/experiences/${expId}/time-ranges`, rest);
  }

  async copyTimeRange(payload: CopyTimeRangeRequest): Promise<Response<any>> {
    const { expId, ...rest } = payload;
    return this.postRequest(`/experiences/${expId}/time-ranges/copy`, rest);
  }

  async updateTimeRange(
    payload: UpdateTimeRangeRequest,
  ): Promise<Response<any>> {
    const { expId, id, ...rest } = payload;
    return this.putRequest(`/experiences/${expId}/time-ranges/${id}`, rest);
  }

  async setRepeatTimeRange(
    payload: RepeatTimeRangeRequest,
  ): Promise<Response<any>> {
    const { expId, ...rest } = payload;
    return this.postRequest(
      `/experiences/${expId}/time-ranges/set-repeat`,
      rest,
    );
  }

  async removeRepeatTimeRange(
    payload: RepeatTimeRangeRequest,
  ): Promise<Response<any>> {
    const { expId, ...rest } = payload;
    return this.putRequest(
      `/experiences/${expId}/time-ranges/remove-repeat`,
      rest,
    );
  }

  async createDateOff(payload: CreateDateOffRequest): Promise<Response<any>> {
    const { expId, ...rest } = payload;
    return this.postRequest(`/experiences/${expId}/date-off`, rest);
  }

  async deleteTimeRange(
    payload: DeleteTimeRangeRequest,
  ): Promise<Response<any>> {
    const { expId, id } = payload;
    return this.deleteRequest(`/experiences/${expId}/time-ranges/${id}`);
  }

  async deleteDateOff(payload: DeleteDateOffRequest): Promise<Response<any>> {
    const { expId, dateOffId } = payload;
    return this.deleteRequest(`/experiences/${expId}/date-off/${dateOffId}`);
  }

  async deleteWeekDay(payload: DeleteWeekDayRequest): Promise<Response<any>> {
    const { expId, ...rest } = payload;
    return this.postRequest(
      `/experiences/${expId}/time-ranges/delete-weekday`,
      rest,
    );
  }

  async createTalentProfile(
    payload: TalentProfileRequest,
  ): Promise<Response<any>> {
    return this.postRequest("talent-profiles", payload);
  }

  async getTalentProfileById(id: string): Promise<Response<any>> {
    return this.getRequest(`talent-profiles/${id}`);
  }

  async updateTalentProfileById(
    id: string,
    payload: TalentProfileRequest,
  ): Promise<Response<any>> {
    return this.patchRequest(`talent-profiles/${id}`, payload);
  }

  async createTalentProfileModule(
    payload: CreateTalentProfileModuleRequest<TalentModuleMixItem>,
  ): Promise<Response<any>> {
    return this.postRequest("users/me/talent-profile-modules", payload);
  }

  async updateTalentProfileModule(
    payload: UpdateTalentProfileModuleRequest<TalentModuleMixItem>,
  ): Promise<Response<any>> {
    return this.patchRequest(
      `users/me/talent-profile-modules/${payload.id}`,
      payload,
    );
  }

  async reorderTalentProfileModule(
    payload: ReorderTalentProfileModuleRequest[],
  ): Promise<Response<any>> {
    return this.putRequest("users/me/talent-profile-modules/re-order", payload);
  }

  async deleteTalentProfileModule(
    payload: TalentProfileModule<TalentModuleMixItem>,
  ): Promise<Response<any>> {
    return this.deleteRequest(`users/me/talent-profile-modules/${payload.id}`);
  }

  async getCollaborator(): Promise<Response<any>> {
    return this.getRequest("users/me/talent-profiles/collaborator-invitations");
  }

  async inviteCollaborator(
    payload: InviteCollaboratorRequest,
  ): Promise<Response<any>> {
    return this.postRequest(
      "users/me/talent-profiles/collaborator-invitations",
      payload,
    );
  }

  async cancelInviteCollaborator(
    payload: CancelInviteCollaboratorRequest,
  ): Promise<Response<any>> {
    return this.deleteRequestWithPayload(
      "users/me/talent-profiles/collaborator-invitations/cancel",
      payload,
    );
  }

  async revokeInviteCollaborator(
    payload: RevokeInviteCollaboratorRequest,
  ): Promise<Response<any>> {
    return this.deleteRequestWithPayload(
      "users/me/talent-profiles/collaborator-invitations/revoke",
      payload,
    );
  }
  async resendInviteCollaborator(
    payload: ResendInviteCollaboratorRequest,
  ): Promise<Response<any>> {
    return this.postRequest(
      "users/me/talent-profiles/collaborator-invitations/resend",
      payload,
    );
  }

  resendEmailConfirmation(userId: number) {
    return this.postRequest("auth/activate/email", { userId });
  }

  async verifyBecomeTalentOtp(
    payload: VerifyBecomeTalentOtpRequest,
  ): Promise<Response<any>> {
    return this.patchRequest("users/me/consumer-profile", payload);
  }

  async finishTalentProfile(
    payload: FinishTalentProfileRequest,
  ): Promise<Response<any>> {
    return this.postRequest("talent-profiles/finish-talent-profile", payload);
  }

  async updateTalentProfile(
    payload: TalentProfileRequest,
  ): Promise<Response<any>> {
    return this.patchRequest("users/me/talent-profiles", payload);
  }
  async getUserByUsername(username: string): Promise<Response<User>> {
    return this.getRequest(`/users/usernames/${encodeURIComponent(username)}`);
  }

  async getCategories(): Promise<Response<Pagination<Category[] | null>>> {
    return this.getRequest("categories/list");
  }

  async getTags(
    payload: ListQueryParams & Required<{ search: string }>,
  ): Promise<Response<any>> {
    return this.getRequest("tags", payload);
  }

  async updatePassword(payload: UpdatePasswordRequest): Promise<Response<any>> {
    return this.postRequest("users/update-password", payload);
  }

  async sendPhoneOTP(
    payload: SendPhoneOTPRequest,
  ): Promise<Response<PhoneOTP>> {
    return this.getRequest(`users/send-phone-verification`, payload);
  }

  async sendEmailOTP(payload: SendEmailOTPRequest): Promise<Response<boolean>> {
    return this.postRequest(`auth/verify-email/send`, payload);
  }

  async getTalentAnalytic(
    payload: GetAnalyticRequest,
  ): Promise<Response<Analytics>> {
    return this.getRequest("/analytic/me/talent", payload);
  }

  async createPayoutMethod(
    payload: AddPayoutMethodRequest,
  ): Promise<Response<any>> {
    return this.postRequest("users/me/payouts/payment-methods", payload);
  }

  async getPayoutSchedule(): Promise<Response<PayoutSchedule>> {
    return this.getRequest("/payments/payouts/schedule");
  }

  getProducts(payload: ProductRequest): Promise<Response<Pagination<Product>>> {
    return this.getRequest("/products", payload);
  }

  async createProduct(payload: Product): Promise<Response<any>> {
    return this.postRequest("/products", payload);
  }

  async updateProduct(
    productId: string,
    payload: Product,
  ): Promise<Response<any>> {
    return this.patchRequest(`/products/${productId}`, payload);
  }

  async getProductById(productId: string): Promise<Response<any>> {
    return this.getRequest(`/products/${productId}`);
  }

  async deleteProductById(productId: string): Promise<Response<any>> {
    return this.deleteRequest(`/products/${productId}`);
  }

  async getIAPSkus(): Promise<Response<any>> {
    return this.getRequest(`/transactions/iap/skus`, {
      type: "APPLE_IAP",
    });
  }

  async getListSpecialRequests(
    payload: GetSpecialRequests,
  ): Promise<Response<Pagination<SpecialRequest[]>>> {
    return this.getRequest(`users/${payload?.userId}/bookings`, {
      ...payload.params,
      type: [EXPERIENCE_TYPE.SPECIAL_REQUEST],
    });
  }

  async updateBooking(payload: Booking): Promise<Response<Booking>> {
    const { id } = payload;
    return this.putRequest(`/bookings/${id}`, payload);
  }

  async getSpecialRequestById(id: string): Promise<Response<SpecialRequest>> {
    return this.getRequest(`/bookings/${id}`);
  }

  async acceptBooking(bookingId: Booking["id"]): Promise<any> {
    return this.postRequest(`/bookings/${bookingId}/accept`);
  }

  async getCalendars(): Promise<Response<any>> {
    return this.getRequest("/calendars");
  }

  async calendarCronofyRequestAuthorizationCode(payload: {
    provider_name: string;
    redirect_uri: string;
    state: string;
  }): Promise<Response<any>> {
    return this.getRequest("/calendars/request-authorization-code", payload);
  }

  async calendarCronofyRequestAuthorizationToken(payload: {
    code: string;
    redirect_uri: string;
  }): Promise<Response<any>> {
    return this.getRequest("/calendars/request-authorization-token", payload);
  }

  async revokeCalendarCronofy(
    providerName: CALENDAR_PROVIDERS,
  ): Promise<Response<any>> {
    return this.deleteRequest("/calendars/revoke-authorization", {
      provider_name: providerName,
    });
  }

  async createAvailability(payload: CreateAvailabilityRule): Promise<any> {
    return this.postRequest(
      `/calendars/scheduling/availability-rules`,
      payload,
    );
  }

  async updateAvailability(payload: UpdateAvailabilityRule): Promise<any> {
    return this.putRequest(`/calendars/scheduling/availability-rules`, payload);
  }

  async getAvailableRules(): Promise<any> {
    return this.getRequest(`/calendars/scheduling/availability-rules`);
  }

  getAvailablePeriod(
    payload: GetAvailablePeriodRequest,
  ): Promise<Response<GetAvailablePeriodResponse>> {
    return this.getRequest("/calendars/scheduling/available-periods", payload);
  }

  createAvailablePeriod(
    payload: CreateAvailablePeriodRequest,
  ): Promise<Response<any>> {
    return this.postRequest("/calendars/scheduling/available-periods", payload);
  }

  deleteAvailablePeriod(payload: string[]): Promise<Response<any>> {
    return this.deleteRequestWithPayload(
      "/calendars/scheduling/available-periods",
      payload,
    );
  }

  async checkUserExisted(
    params: CheckUserExistedRequest,
  ): Promise<Response<CheckUserExistedResult>> {
    return this.getRequest(`users/check-is-existed`, params);
  }

  async stripeConnect(
    params: StripeConnectRequest,
  ): Promise<Response<StripeConnectResponse>> {
    return this.getRequest(`/payments/accounts/link`, params);
  }

  async spotifyConnect(
    params: SpotifyConnectRequest,
  ): Promise<Response<SpotifyConnectResponse>> {
    return this.getRequest(`/integrations/spotify/auth`, params);
  }

  async spotifyRefreshToken(): Promise<Response<SpotifyUser>> {
    return this.getRequest(`/integrations/spotify/token`);
  }

  async getExchangeRates(
    localCurrency: string,
  ): Promise<Response<ExchangeRate>> {
    return this.getRequest(`/payments/gbp-exchange-rate`, {
      localCurrency: localCurrency,
    });
  }

  async getLocation(): Promise<any> {
    try {
      const response = await this.apisauceSecure.get(
        `https://ipinfo.io/json?token=${window.env.REACT_APP_IP_GEO_LOCATION}`,
      );
      return {
        ok: true,
        response: response?.data,
      };
    } catch (error) {
      return {
        message: error,
      };
    }
  }

  async getDataCaptureForm(): Promise<Response<any>> {
    return this.getRequest(`/users/me/talent-profile-modules/forms`);
  }

  async exportDataCaptureCSV(
    data: ExportDataFormRequest,
  ): Promise<Response<any>> {
    const response = await this.apisauceSecure.post(
      `/users/me/talent-profile-modules/forms/answers`,
      data,
      { responseType: "blob" },
    );
    if (!response.ok) {
      return getGeneralApiProblem(response);
    }
    return { ok: response.ok, response };
  }

  async exportFanClubCSV(data: ExportFanClubRequest): Promise<Response<any>> {
    const response = await this.apisauceSecure.post(
      `/users/fan-club/report`,
      data,
      { responseType: "blob" },
    );
    if (!response.ok) {
      return getGeneralApiProblem(response);
    }
    return { ok: response.ok, response };
  }
  async getFanClubCount(
    data: ExportFanClubRequest,
  ): Promise<Response<getFanClubCountResult>> {
    return this.postRequest(`/users/fan-club/count`, data);
  }
  async getDataFormCount(
    data: ExportDataFormRequest,
  ): Promise<Response<getDataFormCountResult>> {
    return this.postRequest(
      `/users/me/talent-profile-modules/forms/answers/count`,
      data,
    );
  }
  async getListDataForm(): Promise<Response<DataForm[]>> {
    return this.getRequest(`/users/me/talent-profile-modules/forms`);
  }

  async getListPreRelease(): Promise<Response<DataForm[]>> {
    return this.getRequest(`/users/me/talent-profile-modules/music-presave`);
  }

  async getPreReleaseCount(
    data: ExportDataFormRequest,
  ): Promise<Response<getDataFormCountResult>> {
    return this.postRequest(
      `/users/me/talent-profile-modules/music-presave/count`,
      data,
    );
  }

  async exportPreReleaseCSV(
    data: any, //Fix with interface
  ): Promise<Response<any>> {
    const response = await this.apisauceSecure.post(
      `/users/me/talent-profile-modules/music-presave/export`,
      data,
      { responseType: "blob" },
    );
    if (!response.ok) {
      return getGeneralApiProblem(response);
    }
    return { ok: response.ok, response };
  }

  async getAuthShopifyUrl(storeDomain: string): Promise<any> {
    const response = await this.apisauceSecure.get(
      `/shopify/${storeDomain}/auth-url`,
    );
    if (!response.ok) {
      return getGeneralApiProblem(response);
    }
    return { ok: response.ok, data: response?.data };
  }

  async updateShopifyStoreName(
    storeDomain: string,
    name: string,
  ): Promise<any> {
    return this.patchRequest(`/shopify/${storeDomain}`, {
      name,
    });
  }

  async updateShopifyStoreStatus(
    storeDomain: string,
    connected: boolean,
  ): Promise<any> {
    return this.patchRequest(`/shopify/${storeDomain}`, {
      connected,
    });
  }

  async removeShopifyStore(storeDomain: string): Promise<any> {
    return this.deleteRequest(`/shopify/${storeDomain}`);
  }

  async reorderShopifyStore(
    payload: ReorderShopifyStoreRequest[],
  ): Promise<Response<any>> {
    return this.putRequest("/shopify/token/re-order", payload);
  }

  async autoSaveProfile(payload: autoSaveProfileRequest): Promise<any> {
    return this.patchRequest("/users/me/talent-profiles/save", payload);
  }

  async publishProfile(payload: publishProfileRequest): Promise<any> {
    return this.patchRequest("/users/me/talent-profiles/publish", payload);
  }

  async deleteLocalization({
    localizationId,
    talentProfileId,
  }: DeleteLocalizationRequest): Promise<any> {
    return this.deleteRequest(
      `/talent-profiles/${talentProfileId}/localization/${localizationId}`,
    );
  }

  async getLocalizationModules(
    talentProfileId: string,
    localizationId: string,
  ): Promise<any> {
    return this.getRequest(
      `/talent-profiles/${talentProfileId}/localization-modules`,
      { localizationId },
    );
  }
  async requestOtp(data: requestOTPRequest): Promise<any> {
    return this.postRequest(`/auth/request-otp`, data);
  }
  async TFAVerification(data: TFAVerificationRequest): Promise<any> {
    return this.patchRequest(`/users/2fa-verification`, data);
  }
  async deleteTFAVerification(data: TFAVerificationRequest): Promise<any> {
    return this.deleteRequestWithPayload(`/users/2fa-verification`, data);
  }

  async getDspResourceLinks(
    resource: DspResource,
  ): Promise<Response<DspLinkPayload[]>> {
    return this.postRequest<DspResource, DspLinkPayload[]>(
      `/users/music/smartlinks/search`,
      resource,
    );
  }

  async getYoutubeCollections(
    resource: YoutubeParams,
  ): Promise<Response<YoutubeResponse>> {
    return this.getRequest<YoutubeParams, YoutubeResponse>(
      `/youtube/metadata`,
      resource,
    );
  }
  async getUploadTokens(payload: DigitalProductUploadBody): Promise<Response<DigitalProductUploadTokenResponse>> {
    return this.postRequest<DigitalProductUploadBody, DigitalProductUploadTokenResponse>(`/modules/product/upload`, payload);
  }
  async validateMetaPixel(data: MetaPixelParams): Promise<Response<any>> {
    return this.postRequest<MetaPixelParams, any>(`/meta-pixel/validate`, data);
  }
  async validatePodcastLinks(
    data: PodcastValidateParams,
  ): Promise<Response<any>> {
    return this.postRequest<PodcastValidateParams, any>(
      `/podcast/validate-url`,
      data,
    );
  }
  async getSyncLatestPodcasts(
    resource: PodcastSyncLatestParams,
  ): Promise<Response<any>> {
    return this.getRequest<PodcastSyncLatestParams, any>(
      `/podcast/metadata`,
      resource,
    );
  }
  async getValidateSeatedById(id: any): Promise<any> {
    return this.getRequest<PodcastSyncLatestParams, any>(
      `/seated/${id.trim()}/validate`,
    );
  }
  async getMetadataSeatedById(id: any): Promise<any> {
    return this.getRequest<PodcastSyncLatestParams, any>(
      `/seated/${id.trim()}/metadata`,
    );
  }

  async requestTalentProfile(
    payload: RequestTalentProfileRequest,
  ): Promise<Response<any>> {
    return this.postRequest(`/talent-profiles/top-talent-request`, payload);
  }

  getCustomerInfo(): Promise<Response<CustomerWithDetailsSuccess>> {
    return this.getRequest("/sales/customers/me");
  }

  deletePaymentMethod(): Promise<Response<boolean>> {
    return this.postRequest("/sales/customers/payment-method/delete", {
      setup: true, // FIXME: does not work with empty payload
    });
  }

  createSetup(): Promise<Response<StripeSetupIntentSuccess>> {
    return this.postRequest("/sales/customers/setup", {
      setup: true, // FIXME: does not work with empty payload
    });
  }

  confirmSetup(setup_id: string): Promise<Response<SalesSuccess>> {
    return this.postRequest("/sales/customers/confirm", {
      setup_id,
    });
  }

  chargePayment(product_key: ProductKey): Promise<Response<SalesSuccess>> {
    return this.postRequest("/sales/customers/charge", {
      product_key,
    });
  }

  getSalesProducts(product_key: ProductKey): Promise<Response<ProductSuccess>> {
    return this.getRequest(`/sales/products/${product_key}`);
  }

  cancelSubscription(product_key: ProductKey): Promise<Response<SalesSuccess>> {
    return this.postRequest(`/sales/subscriptions/${product_key}/cancel`, {
      product_key, //post requires body
    });
  }

  checkoutSubscription(
    product_key: ProductKey,
    interval: Interval,
  ): Promise<Response<SalesSuccess>> {
    return this.postRequest(`/sales/subscriptions/${product_key}/checkout`, {
      interval,
    });
  }

  cancelSubscriptionFeedback(
    product_key: ProductKey,
    feedback: CancelFeedback,
  ): Promise<Response<SalesSuccess>> {
    return this.patchRequest(`/sales/subscriptions/${product_key}/cancel`, {
      feedback,
    });
  }

  createSubscription(
    product_key: ProductKey,
    interval: Interval,
  ): Promise<Response<SubscriptionSuccess>> {
    return this.postRequest(`/sales/subscriptions`, {
      product_key,
      interval,
    });
  }

  updateSubscription(
    product_key: ProductKey,
    interval: Interval,
  ): Promise<Response<SubscriptionSuccess>> {
    return this.patchRequest(`/sales/subscriptions`, {
      product_key,
      interval,
    });
  }

  canDeletePaymentMethod(): Promise<Response<CanDeletePaymentMethodSuccess>> {
    return this.getRequest("/sales/customers/payment-method/can-delete");
  }

  // Campaigns
  getCampaign(
    talent_profile_id: string,
    campaign_id: string,
  ): Promise<Response<CampaignResponse>> {
    return this.getRequest(
      `/talent-profiles/${talent_profile_id}/campaign/${campaign_id}/`,
    );
  }

  getCampaignReport(
    talent_profile_id: string,
    campaign_id: string,
  ): Promise<Response<CampaignReportResponse>> {
    return this.getRequest(
      `/talent-profiles/${talent_profile_id}/campaign/${campaign_id}/report`,
    );
  }

  getCampaigns(
    talent_profile_id: string,
  ): Promise<Response<CampaignsResponse>> {
    return this.getRequest(`/talent-profiles/${talent_profile_id}/campaigns`);
  }

  getCampaignsWithCursor(
    queryParams: PaginationQueryParameters,
    talent_profile_id: string,
    searchTerm: string,
  ): Promise<Response<CampaignsWithCursorResponse>> {
    return this.retryRequest(() =>
      this.getRequest(`/talent-profiles/${talent_profile_id}/campaigns-v2`, {
        ...queryParams,
        searchTerm,
      }),
    );
  }

  getCampaignsCount(
    countParams: CountQueryParameters,
    talent_profile_id: string,
    searchTerm: string,
  ): Promise<Response<CountQueryResponse>> {
    return this.retryRequest(() =>
      this.getRequest(
        `/talent-profiles/${talent_profile_id}/campaigns-v2/count`,
        {
          ...countParams,
          searchTerm,
        },
      ),
    );
  }

  createCampaign(
    talent_profile_id: string,
    payload: CampaignUpsertDto,
  ): Promise<Response<CampaignResponse>> {
    return this.postRequest(
      `/talent-profiles/${talent_profile_id}/campaigns/`,
      payload,
    );
  }

  patchCampaign(
    talent_profile_id: string,
    campaign_id: string,
    payload: DeepPartial<CampaignUpsertDto>,
  ): Promise<Response<CampaignResponse>> {
    return this.patchRequest(
      `/talent-profiles/${talent_profile_id}/campaigns/${campaign_id}/`,
      payload,
    );
  }

  deleteCampaign(campaignId: string): Promise<Response<boolean>> {
    return this.deleteRequest(`/campaigns/${campaignId}`);
  }

  // Segments
  async countSegmentQueryById(
    segmentId: string,
  ): Promise<Response<CountQueryResponse>> {
    return this.getRequest(`/segments/${segmentId}/query/count`);
  }

  async countSegmentQuery(
    segment: Segment,
  ): Promise<Response<CountQueryResponse>> {
    return this.postRequest(`/segments/query/count`, { segment });
  }

  async getSegments(): Promise<Response<GetAllSegments>> {
    return this.getRequest(`/segments`);
  }

  async getSegmentsWithCursor(
    queryParams: PaginationQueryParameters,
    searchTerm: string,
  ): Promise<Response<GetAllSegmentsPaginated>> {
    const payload = {
      ...queryParams,
      searchTerm,
    };

    return this.retryRequest(() => this.getRequest(`/segments-v2`, payload));
  }

  async getSegmentsCount(
    countParams: CountQueryParameters,
    searchTerm: string,
  ): Promise<Response<CountQueryResponse>> {
    const payload = {
      ...countParams,
      searchTerm,
    };

    return this.retryRequest(() =>
      this.getRequest(`/segments-v2/count`, payload),
    );
  }

  async getSegment(segmentId: string): Promise<Response<GetSegmentResponse>> {
    return this.getRequest(`/segments/${segmentId}`);
  }

  async getSegmentByName(name: string): Promise<Response<GetSegmentResponse>> {
    return this.getRequest(`/segment?name=${name}`);
  }

  async createSegment(
    segment: Segment,
  ): Promise<Response<CreateSegmentResponse>> {
    return this.postRequest(`/segments`, { segment });
  }

  async updateSegment(
    segment: Segment,
  ): Promise<Response<UpdateSegmentResponse>> {
    return this.patchRequest(`/segments/${segment.segmentId}`, { segment });
  }

  async deleteSegment(
    segmentId: string,
  ): Promise<Response<DeleteSegmentResponse>> {
    return this.deleteRequest(`/segments/${segmentId}`);
  }

  async segmentExists(name: string): Promise<Response<{ exists: boolean }>> {
    return this.getRequest(`/segments/exists?name=${name}`);
  }

  // Templates
  async getTemplate(templateId: string): Promise<Response<TemplateResponse>> {
    return this.getRequest(`/templates/${templateId}`);
  }

  async getTemplates(): Promise<Response<TemplatesResponse>> {
    return this.getRequest(`/templates`);
  }

  async getTemplatesWithCursor(
    queryParams: PaginationQueryParameters,
    searchTerm: string,
  ): Promise<Response<TemplatesWithCursorResponse>> {
    return this.retryRequest(() =>
      this.getRequest(`/templates-v2`, {
        ...queryParams,
        searchTerm,
      }),
    );
  }

  async getTemplatesCount(
    countParams: CountQueryParameters,
    searchTerm: string,
  ): Promise<Response<CountQueryResponse>> {
    return this.retryRequest(() =>
      this.getRequest(`/templates-v2/count`, {
        ...countParams,
        searchTerm,
      }),
    );
  }

  async updateTemplate(
    templateId: string,
    payload: Partial<TemplateDto>,
  ): Promise<Response<TemplateResponse>> {
    return this.patchRequest(`/templates/${templateId}`, payload);
  }

  async createTemplate(
    payload: CampaignTemplateCreateDto,
  ): Promise<Response<TemplateResponse>> {
    return this.postRequest(`/templates`, payload);
  }

  async deleteTemplate(templateId: string): Promise<Response<boolean>> {
    return this.deleteRequest(`/templates/${templateId}`);
  }

  async getSignedThumbnailUploadUrl(): Promise<
    Response<TemplateSignedUrlResponse>
  > {
    return this.getRequest(`/templates/thumbnail/upload-url`);
  }

  // Campaign Templates
  async getCampaignTemplate(
    campaignTemplateId: string,
  ): Promise<Response<CampaignTemplateResponse>> {
    return this.getRequest(`/campaign-templates/${campaignTemplateId}`);
  }

  async updateCampaignTemplate(
    campaignTemplateId: string,
    payload: Partial<TemplateDto>,
  ): Promise<Response<TemplateResponse>> {
    return this.patchRequest(
      `/campaign-templates/${campaignTemplateId}`,
      payload,
    );
  }

  async createCampaignTemplate(
    payload: CampaignTemplateCreateDto,
  ): Promise<Response<CampaignTemplateResponse>> {
    return this.postRequest(`/campaign-templates`, payload);
  }

  async checkCampaignNameExists(
    talentProfileId: string,
    campaignId: string,
    name: string,
  ): Promise<Response<CheckNameExistsResponse>> {
    return this.getRequest("/campaign/checkNameExists", {
      talentProfileId,
      campaignId,
      name,
    });
  }

  async getFans(
    pageNo: number,
    pageSize: number,
    filter: MarketingPermission,
    searchTerm: string,
  ): Promise<Response<FanSubmission[]>> {
    const payload = {
      pageNo,
      pageSize,
      filter,
      searchTerm,
    };
    const request = `/talent-profiles/fans`;

    return this.getRequest(request, payload);
  }

  async getFansWithCursor(
    queryParams: PaginationQueryParameters,
    filter: MarketingPermission,
    searchTerm: string,
  ): Promise<Response<FanWithCursorResponseSchema[]>> {
    const payload = {
      ...queryParams,
      filter,
      searchTerm,
    };
    const request = `/talent-profiles/fans-v2`;

    return this.retryRequest(() => this.getRequest(request, payload));
  }

  async getTotalFanCount(
    filter: MarketingPermission,
    searchTerm: string,
  ): Promise<Response<number>> {
    const request = `/talent-profiles/fans/count`;

    return this.getRequest(request, { filter, searchTerm });
  }

  async getTotalFanCountWithCursor(
    countParams: CountQueryParameters,
    filter: MarketingPermission,
    searchTerm: string,
  ): Promise<Response<CountQueryResponse>> {
    const request = `/talent-profiles/fans-v2/count`;

    return this.retryRequest(() =>
      this.getRequest(request, { ...countParams, filter, searchTerm }),
    );
  }

  async deleteFans(
    fans: Partial<FanTableSchema>[],
    deletionType: string,
  ): Promise<Response<boolean>> {
    return this.deleteRequestWithPayload(`/talent-profiles/fans`, {
      fans,
      deletionType,
    });
  }
  // Link Redirects

  async getLinkRedirect(): Promise<Response<LinkRedirectResponse>> {
    return this.getRequest(`/talent-profile/link-redirect`);
  }

  async saveLinkRedirect(
    payload: LinkRedirectDto,
  ): Promise<Response<LinkRedirectResponse>> {
    return this.putRequest(`/talent-profile/link-redirect`, payload);
  }

  async updateLinkRedirectStatus(
    payload: LinkRedirectUpdateStatusDto,
  ): Promise<Response<LinkRedirectResponse>> {
    return this.patchRequest(`/talent-profile/link-redirect`, payload);
  }

  async deleteLinkRedirect(): Promise<Response<boolean>> {
    return this.deleteRequest(`/talent-profile/link-redirect`);
  }

  async exportFansAndGetURL(fans: FanTableSchema[], exportType: string) {
    return this.postRequest(`/talent-profiles/fans/exportFans`, {
      fans,
      exportType,
    });
  }

  // Custom domain
  async getEmailDomain(): Promise<Response<GetEmailDomainResponse | null>> {
    return this.getRequest(`/messaging/mail-domain`);
  }

  async deleteEmailDomain(): Promise<Response<undefined>> {
    return this.deleteRequest(`/messaging/mail-domain`);
  }

  async postEmailDomain(
    data: PostEmailDomainRequest,
  ): Promise<Response<GetEmailDomainResponse>> {
    return this.postRequest(`/messaging/mail-domain/authenticate`, data);
  }

  async verifyEmailDomain(): Promise<Response<GetEmailDomainResponse>> {
    return this.getRequest(`/messaging/mail-domain/verify`);
  }

  async patchEmailDomain(
    data: PatchEmailDomainRequest,
  ): Promise<Response<GetEmailDomainResponse>> {
    return this.patchRequest(`/messaging/mail-domain`, data);
  }

  async sendTestEmail(data: PostSendTestEmailRequest): Promise<any> {
    return this.postRequest(`/messaging/email/send/test`, data);
  }
  async getCampaignCountBySegmentId(
    segmentId: string,
  ): Promise<Response<CountQueryResponse>> {
    return await this.getRequest(`/segments/campaigns/${segmentId}`, {
      segmentId,
    });
  }

  async stopCampaign(talentProfileId: string, campaignId: string) {
    return await this.postRequest(
      `/talent-profiles/${talentProfileId}/campaigns/${campaignId}/stop`,
      {},
    );
  }
  async restartCampaign(talentProfileId: string, campaignId: string) {
    return await this.patchRequest(
      `/talent-profiles/${talentProfileId}/campaigns/${campaignId}/restart`,
      {},
    );
  }

  async getDCMorPresavesSubmissions(): Promise<Response<boolean>> {
    return await this.getRequest<boolean>(`talent-profiles/export/exists`);
  }

  async getOneSchemaToken(): Promise<Response<string>> {
    return await this.getRequest<string>(`/contact-import/getToken`);
  }
  async getFansImportInProgress(): Promise<Response<boolean>> {
    return await this.getRequest<boolean>(`/contact-import/getStatus`);
  }

  async startFanImport(
    importEvent: OneSchemaSuccessEvent,
  ): Promise<Response<boolean>> {
    return await this.postRequest(`/contact-import/startImport`, importEvent);
  }

  async getSegmentLocationCountries(): Promise<
    Response<GetGeoCountriesResponse>
  > {
    return await this.getRequest("/segment/locations/countries");
  }

  async getSegmentLocationStates(): Promise<Response<GetGeoStatesResponse>> {
    return await this.getRequest("/segment/locations/states");
  }

  async getSegmentLocationCities(): Promise<Response<GetGeoCitiesResponse>> {
    return await this.getRequest("/segment/locations/cities");
  }
}
