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

export class SettingHandler {
    // set the class variables
    private getSettingServiceObject = async (request: Request) => {
        let variables = await Common.getVariables(request);
        let settingService = new SettingService(variables);
        return settingService;
    }

    // Handles the creation of a new Category Type
    create = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { categoryCode, code, label, value, valueType, status } = request.payload as SettingRequestObject;
            const createSettingInput: SettingCreateServiceInput = { categoryCode, code, label, valueType, value, status };
            let setting: SettingObjectInteface = await settingService.createSetting(createSettingInput);
            await settingService.setAccountSettings();
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: setting }).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 Category Type
    update = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { categoryCode, code, label, value, status, valueType } = request.payload as SettingRequestObject;
            const { id } = request.params as SettingIdentifierObject;
            const updateSettingInput: SettingUpdateServiceInput = { id, categoryCode, code, label, valueType, value, status };
            let setting: SettingObjectInteface = await settingService.updateSetting(updateSettingInput);
            await settingService.setAccountSettings();
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: setting }).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 Category Type
    delete = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { id } = request.params as SettingIdentifierObject;
            const deleteSettingInput: SettingDeleteServiceInput = { id };
            let setting: SettingObjectInteface = await settingService.deleteSetting(deleteSettingInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: setting }).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 Category Type
    getById = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { id } = request.params as SettingIdentifierObject;
            const getByIdInput: SettingGetByIdServiceInput = { id };
            let setting: SettingObjectInteface = await settingService.getById(getByIdInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: setting }).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 Category Type
    getByCode = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { code } = request.params as { code: string };
            const getByCodeInput: SettingGetByCodeServiceInput = { code };
            let setting: SettingObjectInteface = await settingService.getByCode(getByCodeInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: setting }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // list category types with filter
    list = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { categoryCode } = request.params as SettingCategoryCodeIdentifierObject
            let listRequest = request.query as SettingListRequestObject;
            const getSettingsInput: SettingGetSettingsServiceInput = { categoryCode, listRequest };
            let settings: SettingPaginatedList = await settingService.getSettings(getSettingsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: settings }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // listAll category types with filter
    listAll = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { categoryCode } = request.params as SettingCategoryCodeIdentifierObject
            let listRequest = request.query as SettingListAllRequestObject;
            const getAllSettingsInput: SettingGetAllSettingsServiceInput = { categoryCode, listRequest };
            let settings: SettingObjectSummaryInteface[] = await settingService.getAllSettings(getAllSettingsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: settings }).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 content
    listRevisions = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            let listRequest = request.query as SettingListRequestObject;
            let { id } = request.params as SettingIdentifierObject;
            const getSettingsRevisionsInput: SettingGetSettingsRevisionsServiceInput = { id, listRequest };
            let settings: SettingPaginatedList = await settingService.getSettingsRevisions(getSettingsRevisionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: settings }).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 content
    restoreRevision = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { id } = request.params as SettingIdentifierObject;
            const restoreRevisionInput: SettingRestoreRevisionServiceInput = { id };
            let setting: SettingObjectInteface = await settingService.restoreRevision(restoreRevisionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: setting }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // get setting tree
    getSettingTree = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { categoryCode } = request.params as SettingCategoryCodeIdentifierObject
            const getSettingTreeInput: SettingGetSettingTreeServiceInput = { categoryTypeCode: 'setting', code: categoryCode };
            let settingTree: CategoryTree[] = await settingService.getSettingTree(getSettingTreeInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: settingTree }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // set category sortOrder
    setSortOrder = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { id } = request.params as SettingIdentifierObject;
            const { before, after } = request.payload as SettingSortRequest;
            const setSortOrderInput: SettingSetSortOrderServiceInput = { id, before, after };
            let sortOrder = await settingService.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 Setting status
    updateStatus = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { id } = request.params as SettingIdentifierObject;
            const { status } = request.payload as SettingStatusObject;
            const updateStatusInput: SettingUpdateStatusServiceInput = { id, status };
            let setting = await settingService.updateStatus(updateStatusInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: setting }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // update multiple setting in a category
    updateCategorySettings = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let settingService = await this.getSettingServiceObject(request);
            const { categoryCode, settings } = request.payload as SettingUpdateMultipleRequest;
            const updateCategorySettingsInput: SettingUpdateCategorySettingsServiceInput = { categoryCode, settings };
            let categorySettings = await settingService.updateCategorySettings(updateCategorySettingsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: categorySettings }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }
}
