import { Api } from "./api";
import notification from "utils/notification";
import { Maybe } from "types/utilities";
import {
  Campaign,
  CampaignReport,
  CampaignReportResponse,
  CampaignResponse,
  CampaignsResponse,
  CampaignUpsertDto,
  CampaignWithCursor,
} from "types/campaigns";
import {
  CountQueryParameters,
  PaginationQueryParameters,
} from "hooks/usePagination";
import { MessagingAdaptor } from "./api/messaging-adaptor";

export default class CampaignService {
  constructor(
    private readonly api: Api,
    private messagingAdaptor: MessagingAdaptor,
  ) {
    this.api = api;
  }

  async getCampaign(
    talentProfileId: string,
    campaignId: string,
  ): Promise<Maybe<Campaign>> {
    const res = await this.messagingAdaptor.getCampaign(
      talentProfileId,
      campaignId,
    );

    if (!res) {
      return void notification.error({
        message: "Something went wrong while querying cmapaign",
      });
    }
    if (!("ok" in res)) {
      return void notification.error({ message: res.message });
    }

    return res.response.campaign;
  }

  async getCampaignReport(
    talentProfileId: string,
    campaignId: string,
  ): Promise<Maybe<CampaignReport>> {
    const res = await this.messagingAdaptor.getCampaignReport(
      talentProfileId,
      campaignId,
    );

    if (!res) {
      return void notification.error({
        message: "Something went wrong while querying cmapaign report",
      });
    }
    if (!("ok" in res)) {
      return void notification.error({ message: res.message });
    }

    return (res.response as CampaignReportResponse).campaign;
  }

  async getCampaigns(talentProfileId: string): Promise<Maybe<Campaign[]>> {
    const res = await this.api.getCampaigns(talentProfileId);

    if (!res) {
      return void notification.error({
        message: "Something went wrong while querying cmapaigns",
      });
    }
    if (!("ok" in res)) {
      return void notification.error({ message: res.message });
    }

    return (res.response as CampaignsResponse).campaigns;
  }

  async getCampaignsWithCursor(
    queryParams: PaginationQueryParameters,
    talentProfileId: string,
    searchTerm: string,
  ): Promise<Maybe<CampaignWithCursor[]>> {
    const res = await this.messagingAdaptor.getCampaigns(
      queryParams,
      talentProfileId,
      searchTerm,
    );

    if (!res)
      return void notification.error({ message: "Something went wrong" });
    if (!("ok" in res))
      return void notification.error({ message: res.message });

    return res.response.campaigns;
  }

  async getCount(
    countParams: CountQueryParameters,
    talentProfileId: string,
    searchTerm: string,
  ): Promise<Maybe<number>> {
    const res = await this.messagingAdaptor.getCampaignsCount(
      countParams,
      talentProfileId,
      searchTerm,
    );

    if (!res)
      return void notification.error({ message: "Something went wrong" });
    if (!("ok" in res))
      return void notification.error({ message: res.message });

    return res.response.count;
  }

  async createCampaign(
    talentProfileId: string,
    campaign: CampaignUpsertDto,
  ): Promise<Maybe<Campaign>> {
    const res = await this.messagingAdaptor.createCampaign(
      talentProfileId,
      campaign,
    );

    if (!res) {
      return void notification.error({
        message: "Something went wrong while creating campaign",
      });
    }
    if (!("ok" in res)) {
      return void notification.error({ message: res.message });
    }

    return (res.response as CampaignResponse).campaign;
  }

  async updateCampaign(
    talentProfileId: string,
    campaignId: string,
    campaign: CampaignUpsertDto,
  ): Promise<Maybe<Campaign>> {
    const res = await this.messagingAdaptor.patchCampaign(
      talentProfileId,
      campaignId,
      campaign,
    );

    if (!res) {
      return void notification.error({
        message: "Something went wrong while updating campaign",
      });
    }
    if (!("ok" in res)) {
      return void notification.error({ message: res.message });
    }

    return (res.response as CampaignResponse).campaign;
  }

  async checkNameExists(
    talentProfileId: string,
    campaignId: string,
    name: string,
  ): Promise<boolean> {
    const res = await this.messagingAdaptor.checkCampaignNameExists(
      talentProfileId,
      campaignId,
      name,
    );

    if (!res || !("ok" in res)) {
      notification.error({
        message: "Something went wrong while validating campaign name",
      });
      return false;
    }

    return res?.response.nameExists;
  }

  async getCampaignCountBySegmentId(segmentId: string): Promise<number> {
    const ApiResponse = await this.api.getCampaignCountBySegmentId(segmentId);
    if (ApiResponse && "ok" in ApiResponse) return ApiResponse.response.count;
    else throw new Error("Error fetching campaign count");
  }

  async stopCampaign(
    talentProfileId: string,
    campaignId: string,
  ): Promise<string> {
    const ApiResponse = await this.messagingAdaptor.stopCampaign(
      talentProfileId,
      campaignId,
    );

    // NOTE: batchId does not exist
    if (ApiResponse && "ok" in ApiResponse) return ApiResponse.response.batchId;
    else throw new Error("Error fetching batchId");
  }

  async restartCampaign(
    talentProfileId: string,
    campaignId: string,
  ): Promise<boolean> {
    const ApiResponse = await this.messagingAdaptor.restartCampaign(
      talentProfileId,
      campaignId,
    );

    if (ApiResponse && "ok" in ApiResponse) return ApiResponse.ok;
    else return false;
  }

  async deleteCampaign(campaignId: string): Promise<boolean> {
    const ApiResponse = await this.messagingAdaptor.deleteCampaign(campaignId);

    if (ApiResponse && "ok" in ApiResponse) return ApiResponse.ok;
    else return false;
  }
}
