"use strict";
// SPDX-License-Identifier: Apache-2.0
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const ts_jest_1 = require("@golevelup/ts-jest");
const request_1 = require("../request");
const DataFixture_1 = require("../../../../__tests__/fixtures/shared/DataFixture");
const LogService_1 = __importDefault(require("../../../app/service/log/LogService"));
const ValidatedArgs_1 = __importDefault(require("../../../core/validation/ValidatedArgs"));
const ValidationError_1 = require("../../../core/validation/ValidationError");
const BigDecimal_1 = __importDefault(require("../../../domain/context/shared/BigDecimal"));
const SecurityDate_1 = require("../../../domain/context/shared/SecurityDate");
const Dividend_1 = __importDefault(require("./Dividend"));
const EquityFixture_1 = require("../../../../__tests__/fixtures/equity/EquityFixture");
const SetDividendCommand_1 = require("../../../app/usecase/command/dividend/set/SetDividendCommand");
const CancelDividendCommand_1 = require("../../../app/usecase/command/dividend/cancel/CancelDividendCommand");
const GetDividendForQuery_1 = require("../../../app/usecase/query/dividend/getDividendFor/GetDividendForQuery");
const GetDividendQuery_1 = require("../../../app/usecase/query/dividend/getDividend/GetDividendQuery");
const GetDividendsCountQuery_1 = require("../../../app/usecase/query/dividend/getDividendsCount/GetDividendsCountQuery");
const GetDividendHoldersQuery_1 = require("../../../app/usecase/query/dividend/getDividendHolders/GetDividendHoldersQuery");
const GetTotalDividendHoldersQuery_1 = require("../../../app/usecase/query/dividend/getTotalDividendHolders/GetTotalDividendHoldersQuery");
const GetVotingCountQuery_1 = require("../../../app/usecase/query/equity/votingRights/getVotingCount/GetVotingCountQuery");
describe("Dividend", () => {
    let commandBusMock;
    let queryBusMock;
    let networkServiceMock;
    let setDividendRequest;
    let getDividendForRequest;
    let getDividendRequest;
    let getAllDividendsRequest;
    let getDividendHoldersRequest;
    let getTotalDividendHoldersRequest;
    let cancelDividendRequest;
    let handleValidationSpy;
    const transactionId = DataFixture_1.TransactionIdFixture.create().id;
    const factoryAddress = DataFixture_1.HederaIdPropsFixture.create().value;
    const resolverAddress = DataFixture_1.HederaIdPropsFixture.create().value;
    beforeEach(() => {
        commandBusMock = (0, ts_jest_1.createMock)();
        queryBusMock = (0, ts_jest_1.createMock)();
        handleValidationSpy = jest.spyOn(ValidatedArgs_1.default, "handleValidation");
        networkServiceMock = (0, ts_jest_1.createMock)({
            configuration: {
                factoryAddress: factoryAddress,
                resolverAddress: resolverAddress,
            },
        });
        jest.spyOn(LogService_1.default, "logError").mockImplementation(() => { });
        Dividend_1.default.commandBus = commandBusMock;
        Dividend_1.default.queryBus = queryBusMock;
    });
    afterEach(() => {
        jest.resetAllMocks();
        jest.restoreAllMocks();
    });
    describe("setDividend", () => {
        setDividendRequest = new request_1.SetDividendRequest(EquityFixture_1.SetDividendRequestFixture.create());
        it("should set dividends successfully", async () => {
            const expectedResponse = {
                payload: 1,
                transactionId: transactionId,
            };
            commandBusMock.execute.mockResolvedValue(expectedResponse);
            const result = await Dividend_1.default.setDividend(setDividendRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith("SetDividendRequest", setDividendRequest);
            expect(commandBusMock.execute).toHaveBeenCalledTimes(1);
            expect(commandBusMock.execute).toHaveBeenCalledWith(new SetDividendCommand_1.SetDividendCommand(setDividendRequest.securityId, setDividendRequest.recordTimestamp, setDividendRequest.executionTimestamp, setDividendRequest.amountPerUnitOfSecurity));
            expect(result).toEqual(expectedResponse);
        });
        it("should throw an error if command execution fails", async () => {
            const error = new Error("Command execution failed");
            commandBusMock.execute.mockRejectedValue(error);
            await expect(Dividend_1.default.setDividend(setDividendRequest)).rejects.toThrow("Command execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith("SetDividendRequest", setDividendRequest);
            expect(commandBusMock.execute).toHaveBeenCalledWith(new SetDividendCommand_1.SetDividendCommand(setDividendRequest.securityId, setDividendRequest.recordTimestamp, setDividendRequest.executionTimestamp, setDividendRequest.amountPerUnitOfSecurity));
        });
        it("should throw error if securityId is invalid", async () => {
            setDividendRequest = new request_1.SetDividendRequest({
                ...EquityFixture_1.SetDividendRequestFixture.create(),
                securityId: "invalid",
            });
            await expect(Dividend_1.default.setDividend(setDividendRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
        it("should throw error if recordTimestamp is invalid", async () => {
            setDividendRequest = new request_1.SetDividendRequest({
                ...EquityFixture_1.SetDividendRequestFixture.create(),
                recordTimestamp: (Math.ceil(new Date().getTime() / 1000) - 100).toString(),
            });
            await expect(Dividend_1.default.setDividend(setDividendRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
        it("should throw error if executionTimestamp is invalid", async () => {
            const time = Math.ceil(new Date().getTime() / 1000);
            setDividendRequest = new request_1.SetDividendRequest({
                ...EquityFixture_1.SetDividendRequestFixture.create(),
                recordTimestamp: time.toString(),
                executionTimestamp: (time - 100).toString(),
            });
            await expect(Dividend_1.default.setDividend(setDividendRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
        it("should throw error if amountPerUnitOfSecurity is invalid", async () => {
            setDividendRequest = new request_1.SetDividendRequest({
                ...EquityFixture_1.SetDividendRequestFixture.create(),
                amountPerUnitOfSecurity: "invalid",
            });
            await expect(Dividend_1.default.setDividend(setDividendRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
    });
    describe("cancelDividend", () => {
        cancelDividendRequest = new request_1.CancelDividendRequest(EquityFixture_1.CancelDividendRequestFixture.create());
        it("should cancel dividend successfully", async () => {
            const expectedResponse = {
                payload: true,
                transactionId: transactionId,
            };
            commandBusMock.execute.mockResolvedValue(expectedResponse);
            const result = await Dividend_1.default.cancelDividend(cancelDividendRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith("CancelDividendRequest", cancelDividendRequest);
            expect(commandBusMock.execute).toHaveBeenCalledTimes(1);
            expect(commandBusMock.execute).toHaveBeenCalledWith(new CancelDividendCommand_1.CancelDividendCommand(cancelDividendRequest.securityId, cancelDividendRequest.dividendId));
            expect(result).toEqual(expectedResponse);
        });
        it("should throw an error if command execution fails", async () => {
            const error = new Error("Command execution failed");
            commandBusMock.execute.mockRejectedValue(error);
            await expect(Dividend_1.default.cancelDividend(cancelDividendRequest)).rejects.toThrow("Command execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith("CancelDividendRequest", cancelDividendRequest);
        });
        it("should throw error if securityId is invalid", async () => {
            cancelDividendRequest = new request_1.CancelDividendRequest({
                ...EquityFixture_1.CancelDividendRequestFixture.create(),
                securityId: "invalid",
            });
            await expect(Dividend_1.default.cancelDividend(cancelDividendRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
    });
    describe("getDividendFor", () => {
        getDividendForRequest = new request_1.GetDividendForRequest(EquityFixture_1.GetDividendForRequestFixture.create());
        it("should get dividends for successfully", async () => {
            const expectedResponse = {
                tokenBalance: new BigDecimal_1.default(BigInt(10)),
                decimals: 1,
                isDisabled: false,
            };
            queryBusMock.execute.mockResolvedValue(expectedResponse);
            const result = await Dividend_1.default.getDividendFor(getDividendForRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith("GetDividendForRequest", getDividendForRequest);
            expect(queryBusMock.execute).toHaveBeenCalledTimes(1);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetDividendForQuery_1.GetDividendForQuery(getDividendForRequest.targetId, getDividendForRequest.securityId, getDividendForRequest.dividendId));
            expect(result).toEqual(expect.objectContaining({
                tokenBalance: expectedResponse.tokenBalance.toString(),
                decimals: expectedResponse.decimals.toString(),
                isDisabled: expectedResponse.isDisabled,
            }));
        });
        it("should throw an error if query execution fails", async () => {
            const error = new Error("Query execution failed");
            queryBusMock.execute.mockRejectedValue(error);
            await expect(Dividend_1.default.getDividendFor(getDividendForRequest)).rejects.toThrow("Query execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith("GetDividendForRequest", getDividendForRequest);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetDividendForQuery_1.GetDividendForQuery(getDividendForRequest.targetId, getDividendForRequest.securityId, getDividendForRequest.dividendId));
        });
        it("should throw error if targetId is invalid", async () => {
            getDividendForRequest = new request_1.GetDividendForRequest({
                ...EquityFixture_1.GetDividendForRequestFixture.create(),
                targetId: "invalid",
            });
            await expect(Dividend_1.default.getDividendFor(getDividendForRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
        it("should throw error if securityId is invalid", async () => {
            getDividendForRequest = new request_1.GetDividendForRequest({
                ...EquityFixture_1.GetDividendForRequestFixture.create(),
                securityId: "invalid",
            });
            await expect(Dividend_1.default.getDividendFor(getDividendForRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
        it("should throw error if dividendId is invalid", async () => {
            getDividendForRequest = new request_1.GetDividendForRequest({
                ...EquityFixture_1.GetDividendForRequestFixture.create(),
                dividendId: 0,
            });
            await expect(Dividend_1.default.getDividendFor(getDividendForRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
    });
    describe("getDividend", () => {
        getDividendRequest = new request_1.GetDividendRequest(EquityFixture_1.GetDividendRequestFixture.create());
        it("should get dividends successfully", async () => {
            const expectedResponse = {
                dividend: EquityFixture_1.DividendFixture.create(),
            };
            queryBusMock.execute.mockResolvedValue(expectedResponse);
            const result = await Dividend_1.default.getDividend(getDividendRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith("GetDividendRequest", getDividendRequest);
            expect(queryBusMock.execute).toHaveBeenCalledTimes(1);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetDividendQuery_1.GetDividendQuery(getDividendRequest.securityId, getDividendRequest.dividendId));
            expect(result).toEqual(expect.objectContaining({
                dividendId: getDividendRequest.dividendId,
                amountPerUnitOfSecurity: expectedResponse.dividend.amountPerUnitOfSecurity.toString(),
                recordDate: new Date(expectedResponse.dividend.recordTimeStamp * SecurityDate_1.ONE_THOUSAND),
                executionDate: new Date(expectedResponse.dividend.executionTimeStamp * SecurityDate_1.ONE_THOUSAND),
                isDisabled: expectedResponse.dividend.isDisabled,
            }));
        });
        it("should throw an error if query execution fails", async () => {
            const error = new Error("Query execution failed");
            queryBusMock.execute.mockRejectedValue(error);
            await expect(Dividend_1.default.getDividend(getDividendRequest)).rejects.toThrow("Query execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith("GetDividendRequest", getDividendRequest);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetDividendQuery_1.GetDividendQuery(getDividendRequest.securityId, getDividendRequest.dividendId));
        });
        it("should throw error if securityId is invalid", async () => {
            getDividendRequest = new request_1.GetDividendRequest({
                ...EquityFixture_1.GetDividendRequestFixture.create(),
                securityId: "invalid",
            });
            await expect(Dividend_1.default.getDividend(getDividendRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
        it("should throw error if dividendId is invalid", async () => {
            getDividendRequest = new request_1.GetDividendRequest({
                ...EquityFixture_1.GetDividendRequestFixture.create(),
                dividendId: -1,
            });
            await expect(Dividend_1.default.getDividend(getDividendRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
    });
    describe("getAllDividends", () => {
        getAllDividendsRequest = new request_1.GetAllDividendsRequest(EquityFixture_1.GetAllDividendsRequestFixture.create());
        it("should get all dividends successfully", async () => {
            const expectedResponse = {
                payload: 1,
            };
            const expectedResponse2 = {
                dividend: EquityFixture_1.DividendFixture.create(),
            };
            queryBusMock.execute.mockResolvedValueOnce(expectedResponse).mockResolvedValueOnce(expectedResponse2);
            const result = await Dividend_1.default.getAllDividends(getAllDividendsRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith("GetAllDividendsRequest", getAllDividendsRequest);
            expect(queryBusMock.execute).toHaveBeenCalledTimes(2);
            expect(queryBusMock.execute).toHaveBeenNthCalledWith(1, new GetDividendsCountQuery_1.GetDividendsCountQuery(getAllDividendsRequest.securityId));
            expect(queryBusMock.execute).toHaveBeenNthCalledWith(2, new GetDividendQuery_1.GetDividendQuery(getAllDividendsRequest.securityId, 1));
            expect(result).toEqual(expect.arrayContaining([
                {
                    dividendId: 1,
                    amountPerUnitOfSecurity: expectedResponse2.dividend.amountPerUnitOfSecurity.toString(),
                    amountDecimals: expectedResponse2.dividend.amountDecimals,
                    recordDate: new Date(expectedResponse2.dividend.recordTimeStamp * SecurityDate_1.ONE_THOUSAND),
                    executionDate: new Date(expectedResponse2.dividend.executionTimeStamp * SecurityDate_1.ONE_THOUSAND),
                    isDisabled: expectedResponse2.dividend.isDisabled,
                },
            ]));
        });
        it("should return empty array if count is 0", async () => {
            const expectedResponse = {
                payload: 0,
            };
            queryBusMock.execute.mockResolvedValueOnce(expectedResponse);
            const result = await Dividend_1.default.getAllDividends(getAllDividendsRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith("GetAllDividendsRequest", getAllDividendsRequest);
            expect(queryBusMock.execute).toHaveBeenCalledTimes(1);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetDividendsCountQuery_1.GetDividendsCountQuery(getAllDividendsRequest.securityId));
            expect(result).toStrictEqual([]);
        });
        it("should throw an error if query execution fails", async () => {
            const error = new Error("Query execution failed");
            queryBusMock.execute.mockRejectedValue(error);
            await expect(Dividend_1.default.getAllDividends(getAllDividendsRequest)).rejects.toThrow("Query execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith("GetAllDividendsRequest", getAllDividendsRequest);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetVotingCountQuery_1.GetVotingCountQuery(getAllDividendsRequest.securityId));
        });
    });
    describe("getDividendHolders", () => {
        getDividendHoldersRequest = new request_1.GetDividendHoldersRequest(EquityFixture_1.GetDividendHoldersRequestFixture.create());
        it("should get dividend token holders successfully", async () => {
            const expectedResponse = {
                payload: [transactionId],
            };
            queryBusMock.execute.mockResolvedValue(expectedResponse);
            const result = await Dividend_1.default.getDividendHolders(getDividendHoldersRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith(request_1.GetDividendHoldersRequest.name, getDividendHoldersRequest);
            expect(queryBusMock.execute).toHaveBeenCalledTimes(1);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetDividendHoldersQuery_1.GetDividendHoldersQuery(getDividendHoldersRequest.securityId, getDividendHoldersRequest.dividendId, getDividendHoldersRequest.start, getDividendHoldersRequest.end));
            expect(result).toStrictEqual(expectedResponse.payload);
        });
        it("should throw an error if query execution fails", async () => {
            const error = new Error("Query execution failed");
            queryBusMock.execute.mockRejectedValue(error);
            await expect(Dividend_1.default.getDividendHolders(getDividendHoldersRequest)).rejects.toThrow("Query execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith(request_1.GetDividendHoldersRequest.name, getDividendHoldersRequest);
            expect(queryBusMock.execute).toHaveBeenCalledTimes(1);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetDividendHoldersQuery_1.GetDividendHoldersQuery(getDividendHoldersRequest.securityId, getDividendHoldersRequest.dividendId, getDividendHoldersRequest.start, getDividendHoldersRequest.end));
        });
        it("should throw error if securityId is invalid", async () => {
            getDividendHoldersRequest = new request_1.GetDividendHoldersRequest({
                ...EquityFixture_1.GetDividendHoldersRequestFixture.create(),
                securityId: "invalid",
            });
            await expect(Dividend_1.default.getDividendHolders(getDividendHoldersRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
        it("should throw error if dividendId is invalid", async () => {
            getDividendHoldersRequest = new request_1.GetDividendHoldersRequest({
                ...EquityFixture_1.GetDividendHoldersRequestFixture.create(),
                dividendId: -1,
            });
            await expect(Dividend_1.default.getDividendHolders(getDividendHoldersRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
        it("should throw error if start is invalid", async () => {
            getDividendHoldersRequest = new request_1.GetDividendHoldersRequest({
                ...EquityFixture_1.GetDividendHoldersRequestFixture.create(),
                start: -1,
            });
            await expect(Dividend_1.default.getDividendHolders(getDividendHoldersRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
        it("should throw error if end is invalid", async () => {
            getDividendHoldersRequest = new request_1.GetDividendHoldersRequest({
                ...EquityFixture_1.GetDividendHoldersRequestFixture.create(),
                end: -1,
            });
            await expect(Dividend_1.default.getDividendHolders(getDividendHoldersRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
    });
    describe("getTotalDividendHolders", () => {
        getTotalDividendHoldersRequest = new request_1.GetTotalDividendHoldersRequest(EquityFixture_1.GetTotalDividendHoldersRequestFixture.create());
        it("should get total dividend holders successfully", async () => {
            const expectedResponse = {
                payload: 1,
            };
            queryBusMock.execute.mockResolvedValue(expectedResponse);
            const result = await Dividend_1.default.getTotalDividendHolders(getTotalDividendHoldersRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith(request_1.GetTotalDividendHoldersRequest.name, getTotalDividendHoldersRequest);
            expect(queryBusMock.execute).toHaveBeenCalledTimes(1);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetTotalDividendHoldersQuery_1.GetTotalDividendHoldersQuery(getTotalDividendHoldersRequest.securityId, getTotalDividendHoldersRequest.dividendId));
            expect(result).toEqual(expectedResponse.payload);
        });
        it("should throw an error if query execution fails", async () => {
            const error = new Error("Query execution failed");
            queryBusMock.execute.mockRejectedValue(error);
            await expect(Dividend_1.default.getTotalDividendHolders(getTotalDividendHoldersRequest)).rejects.toThrow("Query execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith(request_1.GetTotalDividendHoldersRequest.name, getTotalDividendHoldersRequest);
            expect(queryBusMock.execute).toHaveBeenCalledTimes(1);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetTotalDividendHoldersQuery_1.GetTotalDividendHoldersQuery(getTotalDividendHoldersRequest.securityId, getTotalDividendHoldersRequest.dividendId));
        });
        it("should throw error if securityId is invalid", async () => {
            getTotalDividendHoldersRequest = new request_1.GetTotalDividendHoldersRequest({
                ...EquityFixture_1.GetTotalDividendHoldersRequestFixture.create(),
                securityId: "invalid",
            });
            await expect(Dividend_1.default.getTotalDividendHolders(getTotalDividendHoldersRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
        it("should throw error if dividendId is invalid", async () => {
            getTotalDividendHoldersRequest = new request_1.GetTotalDividendHoldersRequest({
                ...EquityFixture_1.GetTotalDividendHoldersRequestFixture.create(),
                dividendId: -1,
            });
            await expect(Dividend_1.default.getTotalDividendHolders(getTotalDividendHoldersRequest)).rejects.toThrow(ValidationError_1.ValidationError);
        });
    });
});
