import { integratorApiClient } from "auth/data/authService";
import axios from "axios";
import { DTOModel } from "core/dto_model";
import Failure from "core/failure";
import { Service } from "services/domain/serviceEntity";
import { SessionDTO } from "./dto/sessionDTO";
import { SubscriptionDTO } from "./dto/subscriptionDTO";
import { ServiceSession } from "../domain/sessionEntity";
import { SubscriptionRequest } from "./dto/subscriptionRequest";
import ForbidenFailureHandler from "core/handlers/forbidenFailureHandler";
import ExecOnAnyHandler from "core/handlers/execOnAnyFailureHandler";

async function loadSubscriptions(): Promise<Service["id"][]> {
  try {
    const response = await integratorApiClient.get<DTOModel<SubscriptionDTO[]>>(
      "/session"
    );
    const content = response.data.data;
    return content.map((item) => item.service_id);
  } catch (reason) {
    if (axios.isAxiosError(reason)) {
      throw Failure.fromReason(reason, "failures.services.subscriptions");
    }
    throw reason;
  }
}

async function subscribe(payload: SubscriptionRequest): Promise<void> {
  try {
    return await integratorApiClient.post("/session/subscribe", payload);
  } catch (reason) {
    if (axios.isAxiosError(reason)) {
      try {
        const handler = new ForbidenFailureHandler(
          () => {
            throw new Failure({
              status: 403,
              message: "Invalid confirmation credentials",
              key: "failures.subscriptions.confirmation",
            });
          },
          new ExecOnAnyHandler((reason) => {
            throw reason;
          })
        );
        handler.handle(Failure.fromReason(reason));
      } catch (error) {
        return Promise.reject(error);
      }
    }
    throw reason;
  }
}

async function forkTo(id: Service["id"]): Promise<ServiceSession> {
  try {
    return await integratorApiClient.post<DTOModel<SessionDTO>>(
      "/session/login",
      {
        service_id: id,
      },
      {
        withCredentials: true,
      }
    );
  } catch (reason) {
    if (axios.isAxiosError(reason)) {
      throw Failure.fromReason(reason, "failures.services.fork");
    }
    throw reason;
  }
}

export { loadSubscriptions, subscribe, forkTo };
