import { Request, ResponseToolkit, ResponseObject } from "@hapi/hapi";
import { PromotionService } from "../services/promotion.service";
import { AppError } from "../../utils/errors";
import { Common } from "../../utils/common";

export class PromotionHandler {
    private getPromotionServiceObject = async (request: Request) => {
        let variables = await Common.getVariables(request);
        let userService = new PromotionService(variables);
        return userService;
    };

    // Handles the promotion creation
    create = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const payload = request.payload as PromotionRequestObject;
            const createPromotionInput: PromotionCreateServiceInput = {
                title: payload.title,
                description: payload.description,
                imageId: payload.imageId,
                link: payload.link,
                type: payload.type,
                publishAt: payload.publishAt,
                expireAt: payload.expireAt,
                isPremium: payload.isPremium,
                status: payload.status,
            };
            let promotion: PromotionObjectInteface = await promotionService.createPromotion(createPromotionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotion }).code(201);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // Handles the updation of a promotion
    update = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const payload = request.payload as PromotionRequestObject;
            const params = request.params as PromotionIdentifierObject;
            const updatePromotionInput: PromotionUpdateServiceInput = {
                id: params.id,
                title: payload.title,
                description: payload.description,
                imageId: payload.imageId,
                link: payload.link,
                type: payload.type,
                publishAt: payload.publishAt,
                expireAt: payload.expireAt,
                isPremium: payload.isPremium,
                status: payload.status,
            };
            let promotion: PromotionObjectInteface = await promotionService.updatePromotion(updatePromotionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotion }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // Handles the deletion of a promotion
    delete = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const params = request.params as PromotionIdentifierObject;
            const deletePromotionInput: PromotionDeleteServiceInput = { id: params.id };
            let promotion: PromotionObjectInteface = await promotionService.deletePromotion(deletePromotionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotion }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // get promotion by id
    getById = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const params = request.params as PromotionIdentifierObject;
            const getByIdInput: PromotionGetByIdServiceInput = { id: params.id };
            let promotion: PromotionObjectInteface = await promotionService.getById(getByIdInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotion }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // get promotion by code
    getByCode = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const params = request.params as PromotionStringIdentifierObject;
            const getByCodeInput: PromotionGetByCodeServiceInput = { code: params.code };
            let promotion: PromotionObjectInteface = await promotionService.getByCode(getByCodeInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotion }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // list promotion with filter
    list = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const listRequest = request.query as PromotionListRequestObject;
            const params = request.params as PromotionTypeObject;
            const getPromotionsInput: PromotionGetPromotionsServiceInput = { type: params.type, listRequest };
            let promotions: PromotionPaginatedList = await promotionService.getPromotions(getPromotionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotions }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // listAll promotion with filter
    listAll = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const listRequest = request.query as PromotionListAllRequestObject;
            const params = request.params as PromotionTypeObject;
            const getAllPromotionsInput: PromotionGetAllPromotionsServiceInput = {
                type: params.type,
                listRequest,
            };
            let promotions: PromotionObjectSummaryInterface[] = await promotionService.getAllPromotions(getAllPromotionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotions }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // list all revisions of promotion
    listRevisions = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const listRequest = request.query as PromotionListRequestObject;
            const params = request.params as PromotionIdentifierObject;
            const getPromotionsRevisionsInput: PromotionGetPromotionsRevisionsServiceInput = { id: params.id, listRequest };
            let promotions: PromotionPaginatedList = await promotionService.getPromotionsRevisions(getPromotionsRevisionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotions }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // restore promotion
    restoreRevision = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const params = request.params as PromotionIdentifierObject;
            const restorePromotionRevisionInput: PromotionRestoreRevisionServiceInput = { id: params.id };
            let promotion: PromotionObjectInteface = await promotionService.restoreRevision(restorePromotionRevisionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotion }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // set promotion type sort order
    setSortOrder = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const params = request.params as PromotionIdentifierObject;
            const payload = request.payload as PromotionSortRequest;
            const setSortOrderInput: PromotionSetSortOrderServiceInput = {
                id: params.id,
                before: payload.before,
                after: payload.after,
            };
            let sortOrder = await promotionService.setSortOrder(setSortOrderInput);
            if (sortOrder) {
                return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY" }).code(200);
            } else {
                throw new AppError(400, "ERROR_WHILE_UPDATING_SORT_ORDER", {});
            }
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // update promotion status
    updateStatus = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const params = request.params as PromotionIdentifierObject;
            const payload = request.payload as PromotionStatusObject;
            const updatePromotionStatusInput: PromotionUpdateStatusServiceInput = {
                id: params.id,
                status: payload.status,
            };
            let promotion = await promotionService.updateStatus(updatePromotionStatusInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotion }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    getUserPromotions = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let promotionService = await this.getPromotionServiceObject(request);
            const listRequest: PromotionListRequestObject = request.query as PromotionListRequestObject;
            const params = request.params as PromotionTypeObject;
            const status = 1;
            const getPromotionsInput: PromotionGetPromotionsServiceInput = {
                type: params.type,
                listRequest,
                status,
            };
            let promotions: PromotionPaginatedList = await promotionService.getPromotions(getPromotionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: promotions }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };
}
