import { Request, ResponseToolkit, ResponseObject } from "@hapi/hapi";
import { NotificationService } from "../services/notification.service";
import { NOTIFICATION } from "../config/constants";
import { AppError } from "../../utils/errors";
import { Common } from "../../utils/common";

export class NotificationHandler {
    // set the class variables
    private getNotificationServiceObject = async (request: Request) => {
        let variables = await Common.getVariables(request);
        let notificationService = new NotificationService(variables);
        return notificationService;
    };

    // Handles the creation of a new Notification Template
    create = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            const payload = request.payload as NotificationRequestObject;
            const createInput: NotificationCreateServiceInput = {
                title: payload.title,
                code: payload.code,
                body: payload.body,
                status: payload.status ?? NOTIFICATION.STATUS.ACTIVE,
                imageId: payload.imageId,
            };
            let notification: NotificationObjectInteface = await notificationService.createNotification(createInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: notification }).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 Notification Template
    update = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            const payload = request.payload as NotificationRequestObject;
            const params = request.params as NotificationIdentifierObject;
            const updateInput: NotificationUpdateServiceInput = {
                id: params.id,
                title: payload.title,
                code: payload.code,
                body: payload.body,
                status: payload.status ?? NOTIFICATION.STATUS.ACTIVE,
                imageId: payload.imageId,
            };
            let notification: NotificationObjectInteface = await notificationService.updateNotification(updateInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: notification }).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 Notification Template
    delete = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            const params = request.params as NotificationIdentifierObject;
            const deleteInput: NotificationDeleteServiceInput = { id: params.id };
            let notification: NotificationObjectInteface = await notificationService.deleteNotification(deleteInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: notification }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // get notification template by id
    getById = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            const params = request.params as NotificationIdentifierObject;
            const getByIdInput: NotificationGetByIdServiceInput = { id: params.id };
            let notification: NotificationObjectInteface = await notificationService.getById(getByIdInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: notification }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // get notification template by code
    getByCode = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            const params = request.params as any;
            const getByCodeInput: NotificationGetByCodeServiceInput = { code: params.code };
            let notification: NotificationObjectInteface = await notificationService.getByCode(getByCodeInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: notification }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // list notification Templates with filter
    list = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            let listRequest = request.query as NotificationListRequestObject;
            const getNotificationsInput: NotificationGetNotificationsServiceInput = { listRequest };
            let notifications: NotificationPaginatedList = await notificationService.getNotifications(getNotificationsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: notifications }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // list all notification Templates with filter
    listAll = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            let listRequest = request.query as NotificationListAllRequestObject;
            const getAllInput: NotificationGetAllNotificationsServiceInput = { listRequest };
            let notifications: NotificationObjectSummaryInteface[] = await notificationService.getAllNotifications(getAllInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: notifications }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // list revisions of the notification template
    listRevisions = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            let listRequest = request.query as NotificationListRequestObject;
            let params = request.params as NotificationIdentifierObject;
            const revisionsInput: NotificationGetNotificationsRevisionsServiceInput = { id: params.id, listRequest };
            let notifications: NotificationPaginatedList = await notificationService.getNotificationsRevisions(revisionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: notifications }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // restore notification template revision
    restoreRevision = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            const params = request.params as NotificationIdentifierObject;
            const restoreInput: NotificationRestoreRevisionServiceInput = { id: params.id };
            let notification: NotificationObjectInteface = await notificationService.restoreRevision(restoreInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: notification }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // send a test notification
    sendTestNotification = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            const payload = request.payload as { notificationCode: string; replacements: Object };
            let notificationService = await this.getNotificationServiceObject(request);
            const sendInput: NotificationSendServiceInput = { code: payload.notificationCode, replacements: payload.replacements };
            await notificationService.sendNotification(sendInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY" }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };

    // set notification template sort order
    setSortOrder = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            const params = request.params as NotificationIdentifierObject;
            const payload = request.payload as NotificationSortRequest;
            const setSortOrderInput: NotificationSetSortOrderServiceInput = {
                id: params.id,
                before: payload.before,
                after: payload.after,
            };
            let sortOrder = await notificationService.setSortOrder(setSortOrderInput);
            if (sortOrder) return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY" }).code(200);
            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 notification Template status
    updateStatus = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let notificationService = await this.getNotificationServiceObject(request);
            const params = request.params as NotificationIdentifierObject;
            const payload = request.payload as NotificationStatusObject;
            const updateStatusInput: NotificationUpdateStatusServiceInput = { id: params.id, status: payload.status };
            let notification = await notificationService.updateStatus(updateStatusInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: notification }).code(200);
        } catch (err) {
            if (err instanceof AppError) {
                throw err;
            }
            throw new AppError(500, "SOMETHING_WENT_WRONG_IN_SERVICE", err);
        }
    };
}
