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

export class CampaignHandler {
    // set the class variables
    private getCampaignServiceObject = async (request: Request) => {
        let variables = await Common.getVariables(request)
        let campaignService = new CampaignService(variables);
        return campaignService;
    }

    // Handles the creation of a new campaign
    create = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const { title, description, template, attachmentId, parentId, type, status, sendAt, filters,receiverListFileId, isRecurring } = request.payload as CampaignRequestObject;
            const createCampaignInput: CampaignCreateServiceInput = { title, description, template, attachmentId, parentId, type, status, sendAt, filters, receiverListFileId, isRecurring };
            let campaign: CampaignObjectInteface = await campaignService.createCampaign(createCampaignInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).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 campaign
    update = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const { title, description, template, attachmentId, parentId, type, status, sendAt, filters,receiverListFileId, isRecurring } = request.payload as CampaignRequestObject;
            const { id } = request.params as CampaignIdentifierObject;
            const updateCampaignInput: CampaignUpdateServiceInput = { id, title, description, template, attachmentId, parentId, type, status, sendAt, filters, receiverListFileId, isRecurring };
            let campaign: CampaignObjectInteface = await campaignService.updateCampaign(updateCampaignInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).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 campaign
    delete = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const { id, campaignTypeCde } = request.params as { id: number; campaignTypeCde: string; };
            const deleteCampaignInput: CampaignDeleteServiceInput = { id, campaignTypeCode: campaignTypeCde };
            let campaign: CampaignObjectInteface = await campaignService.deleteCampaign(deleteCampaignInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // get campaign by id
    getById = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const { id } = request.params as CampaignIdentifierObject;
            const getCampaignByIdInput: CampaignGetByIdServiceInput = { id };
            let campaign: CampaignObjectInteface = await campaignService.getById(getCampaignByIdInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // get campaign by code
    getByCode = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const { code } = request.params as CampaignStringIdentifierObject;
            const getCampaignByCodeInput: CampaignGetByCodeServiceInput = { code };
            let campaign: CampaignObjectInteface = await campaignService.getByCode(getCampaignByCodeInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // list categories with filter
    list = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            let listRequest = request.query as CampaignListRequestObject;
            const getCampaignsInput: CampaignGetCampaignsServiceInput = { listRequest };
            let categories: CampaignPaginatedList = await campaignService.getCampaigns(getCampaignsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: categories }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // list All categories with filter
    listAll = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            let listRequest = request.query as CampaignListAllRequestObject;
            const getAllCampaignsInput: CampaignGetAllCampaignsServiceInput = { listRequest };
            let campaignTypes: CampaignObjectSummaryInteface[] = await campaignService.getAllCampaigns(getAllCampaignsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaignTypes }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // list all revisions of the campaign
    listRevisions = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            let listRequest = request.query as CampaignListRequestObject;
            let { id } = request.params as CampaignIdentifierObject;
            const getCampaignRevisionsInput: CampaignGetRevisionsServiceInput = { id, listRequest };
            let categories: CampaignPaginatedList = await campaignService.getCampaignRevisions(getCampaignRevisionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: categories }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // restore campaign revision
    restoreRevision = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const { id } = request.params as CampaignIdentifierObject;
            const restoreRevisionInput: CampaignRestoreRevisionServiceInput = { id };
            let campaign: CampaignObjectInteface = await campaignService.restoreRevision(restoreRevisionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // // get campaign tree
    // getCampaignTree = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
    //     try {
    //         let campaignService = await this.getCampaignServiceObject(request);
    //         const { code } = request.params as CampaignStringIdentifierObject;
    //         let campaignTree: CampaignTree[] = await campaignService.getCampaignTree(code);
    //         return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaignTree }).code(200);
    //     } catch (err) {
    //         if (err instanceof AppError) { throw err; }
    //         throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
    //     }
    // }

    // set campaign sort order
    setSortOrder = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const { id, campaignTypeCode } = request.params as CampaignSortIdentifierObject;
            const { before, after } = request.payload as CampaignSortRequest;
            const setSortOrderInput: CampaignSetSortOrderServiceInput = { id, before, after };
            let sortOrder = await campaignService.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 campaign status
    updateStatus = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const { id } = request.params as CampaignIdentifierObject;
            const { status } = request.payload as CampaignStatusObject;
            const updateCampaignStatusInput: CampaignUpdateStatusServiceInput = { id, status };
            let campaign = await campaignService.updateStatus(updateCampaignStatusInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // update campaign status
    addUsersToCampaign = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const { id } = request.payload as CampaignIdentifierObject;
            const addUsersToCampaignInput: CampaignAddUsersServiceInput = { id };
            let campaign = await campaignService.addUsersToCampaign(addUsersToCampaignInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // update campaign status
    listCampaignUsers = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            let listRequest = request.query as CampaignListRequestObject;
            const listCampaignUsersInput: CampaignListUsersServiceInput = { listRequest };
            let campaign = await campaignService.listCampaignUsers(listCampaignUsersInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    generateCampaignReport = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const id = (request.params as CampaignIdentifierObject).id;
            const isComplete = request.query.isComplete ?? true;
            const generateCampaignReportInput: CampaignGenerateReportServiceInput = { id, isComplete: isComplete as boolean };
            let campaign = await campaignService.generateCampaignReport(generateCampaignReportInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    getCampaignLogs = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);
            const id = (request.params as CampaignIdentifierObject).id;
            const isComplete = request.query.isComplete ?? true;
            const page = (request.query as { page: number; }).page;
            const perPage = (request.query as { perPage: number; }).perPage;
            const getCampaignLogsInput: CampaignGetLogsServiceInput = { campaignId: id, isComplete: isComplete as boolean, page, perPage };
            let campaign = await campaignService.getCampaignLogs(getCampaignLogsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: campaign }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    campaignWhatsappWebhook = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let campaignService = await this.getCampaignServiceObject(request);

            const {requestId, eventName, customerNumber} = request.payload as {requestId: string, eventName: string, customerNumber: string};
            const campaignWhatsappWebhookInput: CampaignWhatsappWebhookServiceInput = { requestId, eventName, customerNumber };
            await campaignService.campaignWhatsappWebhook(campaignWhatsappWebhookInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: {} }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }
}
