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

export class AccountHandler {
    // set the class variables
    private getAccountServiceObject = async (request: Request) => {
        let variables = await Common.getVariables(request)
        let accountService = new AccountService(variables);
        return accountService;
    }

    // Handles the creation of a new category type
    create = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let accountService = await this.getAccountServiceObject(request);
            const { name, key, status } = request.payload as AccountRequestObject;
            const createAccountInput: AccountCreateServiceInput = { name, key, status };
            let account: AccountObjectInteface = await accountService.createAccount(createAccountInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: account }).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 accountService = await this.getAccountServiceObject(request);
            const { name, key, status } = request.payload as AccountRequestObject;
            const { id } = request.params as AccountIdentifierObject;
            const updateAccountInput: AccountUpdateServiceInput = { id, name, key, status };
            let account: AccountObjectInteface = await accountService.updateAccount(updateAccountInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: account }).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 accountService = await this.getAccountServiceObject(request);
            const { id } = request.params as AccountIdentifierObject;
            const deleteAccountInput: AccountDeleteServiceInput = { id };
            let account: AccountObjectInteface = await accountService.deleteAccount(deleteAccountInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: account }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // get category type by id
    getById = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let accountService = await this.getAccountServiceObject(request);
            const { id } = request.params as AccountIdentifierObject;
            const getByIdInput: AccountGetByIdServiceInput = { id };
            let account: AccountObjectInteface = await accountService.getById(getByIdInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: account }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // get category type by code
    getByCode = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let accountService = await this.getAccountServiceObject(request);
            const { code } = request.params as AccountStringIdentifierObject;
            const getByCodeInput: AccountGetByCodeServiceInput = { code };
            let account: AccountObjectInteface = await accountService.getByCode(getByCodeInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: account }).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 accountService = await this.getAccountServiceObject(request);
            let listRequest = request.query as AccountListRequestObject;
            const getAccountsInput: AccountGetAccountsServiceInput = { listRequest };
            let accounts: AccountPaginatedList = await accountService.getAccounts(getAccountsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: accounts }).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 accountService = await this.getAccountServiceObject(request);
            let listRequest = request.query as AccountListAllRequestObject;
            const getAllAccountsInput: AccountGetAllAccountsServiceInput = { listRequest };
            let accounts: AccountObjectSummaryInteface[] = await accountService.getAllAccounts(getAllAccountsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: accounts }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // list all revisions of category type
    listRevisions = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let accountService = await this.getAccountServiceObject(request);
            let listRequest = request.query as AccountListRequestObject;
            const { id } = request.params as AccountIdentifierObject;
            const getRevisionsInput: AccountGetRevisionsServiceInput = { id, listRequest };
            let accounts: AccountPaginatedList = await accountService.getAccountsRevisions(getRevisionsInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: accounts }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // restore category type revision
    restoreRevision = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let accountService = await this.getAccountServiceObject(request);
            const { id } = request.params as AccountIdentifierObject;
            const restoreRevisionInput: AccountRestoreRevisionServiceInput = { id };
            let account: AccountObjectInteface = await accountService.restoreRevision(restoreRevisionInput);
            return h.response({ message: "REQUEST_PROCESSED_SUCCESSFULLY", responseData: account }).code(200);
        } catch (err) {
            if (err instanceof AppError) { throw err; }
            throw new AppError(500, 'SOMETHING_WENT_WRONG_IN_SERVICE', err);
        }
    }

    // set category type sort order
    setSortOrder = async (request: Request, h: ResponseToolkit): Promise<ResponseObject> => {
        try {
            let accountService = await this.getAccountServiceObject(request);
            const { id } = request.params as AccountIdentifierObject;
            const { before, after } = request.payload as AccountSortRequest;
            const setSortOrderInput: AccountSetSortOrderServiceInput = { id, before, after };
            let sortOrder = await accountService.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);
        }
    }
}
