import { Action } from "redux-actions";
import { SagaIterator } from "redux-saga";
import { selectUserId } from "redux/User/selector";
import {
  courseService,
  exclusiveContentService,
  experienceService,
  experience1To1Service,
  experienceInteractiveLiveClassService,
  experienceLiveClassService,
  bundleService,
} from "services";
import { call, put, select, takeLatest } from "typed-redux-saga";
import {
  createExclusiveContentActions,
  createExperience1To1Actions,
  createExperienceCourseActions,
  createExperienceBundleActions,
  createExperienceInteractiveLiveClassActions,
  createExperienceLiveClassActions,
  getExperienceByIdActions,
  getExperiencesActions,
  publishExperienceActions,
  updateExclusiveContentActions,
  updateExperience1To1Actions,
  updateExperienceActions,
  updateExperienceCourseActions,
  updateExperienceInteractiveLiveClassActions,
  updateExperienceLiveClassActions,
  updateExperienceBundleActions,
} from "./actions";
import { selectExperienceDetailId } from "./selector";
import {
  Contents1To1Request,
  EXPERIENCE_TYPE,
  GetExperienceByIdRequest,
  GetExperiencePayload,
  PublishExperienceRequest,
  UpdateExperience1To1Request,
  UpdateExperienceRequest,
} from "./types";

function* getExperiences({ payload }: Action<GetExperiencePayload>) {
  let result: any;

  const userId = yield* select(selectUserId);

  switch (payload.type) {
    case EXPERIENCE_TYPE.ONE_TO_ONE:
      result = yield* call(
        experience1To1Service.getExperiences as any,
        userId,
        payload.params
      );
      break;
    case EXPERIENCE_TYPE.LIVE_CLASS:
      result = yield* call(
        experienceLiveClassService.getExperiences as any,
        userId,
        payload.params
      );
      break;
    case EXPERIENCE_TYPE.INTERACTIVE_LIVE_CLASS:
      result = yield* call(
        experienceInteractiveLiveClassService.getExperiences as any,
        userId,
        payload.params
      );

      break;
    case EXPERIENCE_TYPE.EXCLUSIVE_CONTENT:
      result = yield* call(
        exclusiveContentService.getExperiences as any,
        userId,
        payload.params
      );
      break;
    case EXPERIENCE_TYPE.COURSE:
      result = yield* call(
        courseService.getExperiences as any,
        userId,
        payload.params
      );
      break;

    case EXPERIENCE_TYPE.BUNDLE:
      result = yield* call(
        bundleService.getExperiences as any,
        userId,
        payload.params
      );
      break;

    default:
      result = yield* call(
        exclusiveContentService.getAllExperiences as any,
        payload.params
      );
      break;
  }

  if (result?.ok) {
    yield* put(getExperiencesActions.SUCCESS(result.response));
  } else {
    yield* put(getExperiencesActions.FAILURE(result.message));
  }
}

function* getExperienceById({ payload }: Action<string>) {
  const requestData: GetExperienceByIdRequest = {
    expId: payload,
  };

  const result: any = yield* call(
    experience1To1Service.getExperienceById,
    requestData
  );
  if (result.ok) {
    yield* put(getExperienceByIdActions.SUCCESS(result.response));
  } else {
    yield* put(getExperienceByIdActions.FAILURE(result.message));
  }
}

function* createExperience1To1({ payload }: Action<Contents1To1Request>) {
  const id = yield* select(selectExperienceDetailId);
  let result: any;

  if (id)
    result = yield* call(experience1To1Service.updateExperience, {
      requestBody: payload,
      id,
    });
  else result = yield* call(experience1To1Service.createExperience, payload);

  if (result.ok && id) {
    yield* put(updateExperience1To1Actions.SUCCESS(result.response));
  } else if (result.ok) {
    yield* put(createExperience1To1Actions.SUCCESS(result.response));
  } else {
    yield* put(createExperience1To1Actions.FAILURE(result.message));
  }
}

function* updateExperience1To1({
  payload,
}: Action<UpdateExperience1To1Request>) {
  const result: any = yield* call(
    experience1To1Service.updateExperience,
    payload
  );
  if (result.ok) {
    yield* put(updateExperience1To1Actions.SUCCESS(result.response));
  } else {
    yield* put(updateExperience1To1Actions.FAILURE(result.message));
  }
}

function* createExperienceLiveClass({ payload }: Action<Contents1To1Request>) {
  const id = yield* select(selectExperienceDetailId);
  let result: any;

  if (id)
    result = yield* call(experienceLiveClassService.updateExperience, {
      requestBody: payload,
      id,
    });
  else
    result = yield* call(experienceLiveClassService.createExperience, payload);

  if (result.ok && id) {
    yield* put(updateExperienceLiveClassActions.SUCCESS(result.response));
  } else if (result.ok) {
    yield* put(createExperienceLiveClassActions.SUCCESS(result.response));
  } else {
    yield* put(createExperienceLiveClassActions.FAILURE(result.message));
  }
}

function* updateExperienceLiveClass({
  payload,
}: Action<UpdateExperience1To1Request>) {
  const result: any = yield* call(
    experienceLiveClassService.updateExperience,
    payload
  );
  if (result.ok) {
    yield* put(updateExperienceLiveClassActions.SUCCESS(result.response));
  } else {
    yield* put(updateExperienceLiveClassActions.FAILURE(result.message));
  }
}

function* createExperienceInteractiveLiveClass({
  payload,
}: Action<Contents1To1Request>) {
  const id = yield* select(selectExperienceDetailId);
  let result: any;

  if (id)
    result = yield* call(
      experienceInteractiveLiveClassService.updateExperience,
      {
        requestBody: { ...payload, interactive: true },
        id,
      }
    );
  else
    result = yield* call(
      experienceInteractiveLiveClassService.createExperience,
      {
        ...payload,
        interactive: true,
      }
    );

  if (result.ok && id) {
    yield* put(
      updateExperienceInteractiveLiveClassActions.SUCCESS(result.response)
    );
  } else if (result.ok) {
    yield* put(
      createExperienceInteractiveLiveClassActions.SUCCESS(result.response)
    );
  } else {
    yield* put(
      createExperienceInteractiveLiveClassActions.FAILURE(result.message)
    );
  }
}

function* updateExperienceInteractiveLiveClass({
  payload,
}: Action<UpdateExperience1To1Request>) {
  const result: any = yield* call(
    experienceInteractiveLiveClassService.updateExperience,
    payload
  );
  if (result.ok) {
    yield* put(
      updateExperienceInteractiveLiveClassActions.SUCCESS(result.response)
    );
  } else {
    yield* put(
      updateExperienceInteractiveLiveClassActions.FAILURE(result.message)
    );
  }
}

function* createExclusiveContent({ payload }: Action<Contents1To1Request>) {
  const id = yield* select(selectExperienceDetailId);
  let result: any;

  if (id)
    result = yield* call(exclusiveContentService.updateExperience, {
      requestBody: payload,
      id,
    });
  else result = yield* call(exclusiveContentService.createExperience, payload);

  if (result.ok && id) {
    yield* put(updateExclusiveContentActions.SUCCESS(result.response));
  } else if (result.ok) {
    yield* put(createExclusiveContentActions.SUCCESS(result.response));
  } else {
    yield* put(createExclusiveContentActions.FAILURE(result.message));
  }
}

function* updateExclusiveContent({
  payload,
}: Action<UpdateExperience1To1Request>) {
  const result: any = yield* call(
    exclusiveContentService.updateExperience,
    payload
  );
  if (result.ok) {
    yield* put(updateExclusiveContentActions.SUCCESS(result.response));
  } else {
    yield* put(updateExclusiveContentActions.FAILURE(result.message));
  }
}

function* createExperienceCourse({ payload }: Action<Contents1To1Request>) {
  const id = yield* select(selectExperienceDetailId);
  let result: any;

  if (id)
    result = yield* call(courseService.updateExperience, {
      requestBody: payload,
      id,
    });
  else result = yield* call(courseService.createExperience, payload);

  if (result.ok && id) {
    yield* put(updateExperienceCourseActions.SUCCESS(result.response));
  } else if (result.ok) {
    yield* put(createExperienceCourseActions.SUCCESS(result.response));
  } else {
    yield* put(createExperienceCourseActions.FAILURE(result.message));
  }
}

function* updateExperienceCourse({
  payload,
}: Action<UpdateExperience1To1Request>) {
  const result: any = yield* call(courseService.updateExperience, payload);
  if (result.ok) {
    yield* put(updateExperienceCourseActions.SUCCESS(result.response));
  } else {
    yield* put(updateExperienceCourseActions.FAILURE(result.message));
  }
}

function* createExperienceBundle({ payload }: Action<Contents1To1Request>) {
  const id = yield* select(selectExperienceDetailId);
  let result: any;

  if (id)
    result = yield* call(bundleService.updateExperience, {
      requestBody: payload,
      id,
    });
  else result = yield* call(bundleService.createExperience, payload);

  if (result.ok && id) {
    yield* put(updateExperienceBundleActions.SUCCESS(result.response));
  } else if (result.ok) {
    yield* put(createExperienceBundleActions.SUCCESS(result.response));
  } else {
    yield* put(createExperienceBundleActions.FAILURE(result.message));
  }
}

function* updateExperienceBundle({
  payload,
}: Action<UpdateExperience1To1Request>) {
  const result: any = yield* call(bundleService.updateExperience, payload);
  if (result.ok) {
    yield* put(updateExperienceBundleActions.SUCCESS(result.response));
  } else {
    yield* put(updateExperienceBundleActions.FAILURE(result.message));
  }
}

function* updateExperience({ payload }: Action<UpdateExperienceRequest>) {
  const result: any = yield* call(
    experienceService.updateExperienceStatus,
    payload
  );
  if (result.ok) {
    yield* put(updateExperienceActions.SUCCESS(result.response));
  } else {
    yield* put(updateExperienceActions.FAILURE(result.message));
  }
}

function* publishExperience({ payload }: Action<PublishExperienceRequest>) {
  let result: any;

  switch (payload.type) {
    case EXPERIENCE_TYPE.ONE_TO_ONE:
      result = yield* call(experience1To1Service.publishExperience, payload.id);
      break;
    case EXPERIENCE_TYPE.LIVE_CLASS:
      result = yield* call(
        experienceLiveClassService.publishExperience,
        payload.id
      );
      break;
    case EXPERIENCE_TYPE.INTERACTIVE_LIVE_CLASS:
      result = yield* call(
        experienceInteractiveLiveClassService.publishExperience,
        payload.id
      );
      break;
    case EXPERIENCE_TYPE.EXCLUSIVE_CONTENT:
      result = yield* call(
        exclusiveContentService.publishExperience,
        payload.id
      );
      break;
    case EXPERIENCE_TYPE.BUNDLE:
      result = yield* call(bundleService.publishExperience, payload.id);
      break;
    case EXPERIENCE_TYPE.COURSE:
      result = yield* call(courseService.publishExperience, payload.id);
      break;
  }

  if (result.ok) {
    yield* put(publishExperienceActions.SUCCESS(result.response));
  } else {
    yield* put(publishExperienceActions.FAILURE(result?.message || "error"));
  }
}

export default function* experienceSagas(): SagaIterator {
  yield* takeLatest(getExperiencesActions.REQUEST, getExperiences);
  yield* takeLatest(getExperienceByIdActions.REQUEST, getExperienceById);
  yield* takeLatest(updateExperienceActions.REQUEST, updateExperience);
  // 1 to 1
  yield* takeLatest(createExperience1To1Actions.REQUEST, createExperience1To1);
  yield* takeLatest(updateExperience1To1Actions.REQUEST, updateExperience1To1);
  // Live Broadcasts
  yield* takeLatest(
    createExperienceLiveClassActions.REQUEST,
    createExperienceLiveClass
  );
  yield* takeLatest(
    updateExperienceLiveClassActions.REQUEST,
    updateExperienceLiveClass
  );
  // interactive live class
  yield* takeLatest(
    createExperienceInteractiveLiveClassActions.REQUEST,
    createExperienceInteractiveLiveClass
  );
  yield* takeLatest(
    updateExperienceInteractiveLiveClassActions.REQUEST,
    updateExperienceInteractiveLiveClass
  );
  // exclusive content
  yield* takeLatest(
    createExclusiveContentActions.REQUEST,
    createExclusiveContent
  );
  yield* takeLatest(
    updateExclusiveContentActions.REQUEST,
    updateExclusiveContent
  );
  // course
  yield* takeLatest(
    createExperienceCourseActions.REQUEST,
    createExperienceCourse
  );
  yield* takeLatest(
    updateExperienceCourseActions.REQUEST,
    updateExperienceCourse
  );

  // bundle
  yield* takeLatest(
    createExperienceBundleActions.REQUEST,
    createExperienceBundle
  );
  yield* takeLatest(
    updateExperienceBundleActions.REQUEST,
    updateExperienceBundle
  );

  yield* takeLatest(publishExperienceActions.REQUEST, publishExperience);
}
