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

export class PermissionHandler {
    // set the class variables
    private getPermissionServiceObject = async (request: Request) => {
        let variables = await Common.getVariables(request);
        let permissionService = new PermissionService(variables);
        return permissionService;
    }
    // Handles the creation of a new permission
    create = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            const { name, description, categoryCode, status, code } = request.payload as PermissionRequest;
            const createPermissionInput: PermissionCreateServiceInput = { name, description, categoryCode, status, code };
            let permission: PermissionObjectInteface = await permissionService.createPermission(createPermissionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: permission }).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 permission
    update = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            const { name, description, categoryCode, status, code } = request.payload as PermissionRequest;
            const { id } = request.params as PermissionIdentifierObject;
            const updatePermissionInput: PermissionUpdateServiceInput = { id, name, description, categoryCode, status, code };
            let permission: PermissionObjectInteface = await permissionService.updatePermission(updatePermissionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: permission }).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 permission
    delete = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            const { id } = request.params as PermissionIdentifierObject;
            const deletePermissionInput: PermissionDeleteServiceInput = { id };
            let permission: PermissionObjectInteface = await permissionService.deletePermission(deletePermissionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: permission }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // get permission by id
    getById = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            const { id } = request.params as PermissionIdentifierObject;
            const getPermissionByIdInput: PermissionGetByIdServiceInput = { id };
            let permission: PermissionObjectInteface = await permissionService.getById(getPermissionByIdInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: permission }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // get permission by code
    getByCode = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            const { code } = request.params as PermissionStringIdentifierObject;
            const getPermissionByCodeInput: PermissionGetByCodeServiceInput = { code };
            let permission: PermissionObjectInteface = await permissionService.getByCode(getPermissionByCodeInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: permission }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // list permissions with filter
    list = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            let listRequest = request.query as PermissionListRequestObject;
            const getPermissionsInput: PermissionGetPermissionsServiceInput = { listRequest };
            let permissions: PermissionPaginatedList = await permissionService.getPermissions(getPermissionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: permissions }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // list all permissions with filter
    listAll = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            let listRequest = request.query as PermissionListAllRequestObject;
            const getAllPermissionsInput: PermissionGetAllPermissionsServiceInput = { listRequest };
            let permissions: PermissionObjectSummaryInteface[] = await permissionService.getAllPermissions(getAllPermissionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: permissions }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // list all revisions for a permission
    listRevisions = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            let listRequest = request.query as PermissionListRequestObject;
            let { id } = request.params as PermissionIdentifierObject;
            const getPermissionRevisionsInput: PermissionGetPermissionsRevisionsServiceInput = { id, listRequest };
            let permissions: PermissionPaginatedList = await permissionService.getPermissionsRevisions(getPermissionRevisionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: permissions }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // restore revision for a permission
    restoreRevision = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            const { id } = request.params as PermissionIdentifierObject;
            const restorePermissionRevisionInput: PermissionRestoreRevisionServiceInput = { id };
            let permission = await permissionService.restoreRevision(restorePermissionRevisionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: permission }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // get permission tree
    permissionTree = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            let permissionTree = await permissionService.permissionTree();
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: permissionTree }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // set permission sortOrder
    setSortOrder = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            const { id } = request.params as PermissionIdentifierObject;
            const { before, after } = request.payload as PermissionSortRequest;
            const setPermissionSortOrderInput: PermissionSetSortOrderServiceInput = { id, before, after };
            let sortOrder = await permissionService.setSortOrder(setPermissionSortOrderInput);
            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 permission status
    updateStatus = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let permissionService = await this.getPermissionServiceObject(request);
            const { id } = request.params as PermissionIdentifierObject;
            const { status } = request.payload as PermissionStatusObject;
            const updatePermissionStatusInput: PermissionUpdateStatusServiceInput = { id, status };
            let category = await permissionService.updateStatus(updatePermissionStatusInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: category }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }
}
