// SPDX-License-Identifier: Apache-2.0
import { createMock } from "@golevelup/ts-jest";
import { GetNounceRequest, PartitionsProtectedRequest } from "../../request";
import { TransactionIdFixture } from "../../../../../__tests__/fixtures/shared/DataFixture";
import LogService from "../../../../app/service/log/LogService";
import ValidatedRequest from "../../../../core/validation/ValidatedArgs";
import { ValidationError } from "../../../../core/validation/ValidationError";
import Security from "../../../in/security/Security";
import { GetNounceRequestFixture, PartitionsProtectedRequestFixture, } from "../../../../../__tests__/fixtures/protectedPartitions/ProtectedPartitionsFixture";
import { PartitionsProtectedQuery } from "../../../../app/usecase/query/security/protectedPartitions/arePartitionsProtected/PartitionsProtectedQuery";
import { ProtectPartitionsCommand } from "../../../../app/usecase/command/security/operations/protectPartitions/ProtectPartitionsCommand";
import { UnprotectPartitionsCommand } from "../../../../app/usecase/command/security/operations/unprotectPartitions/UnprotectPartitionsCommand";
import { GetNounceQuery } from "../../../../app/usecase/query/security/protectedPartitions/getNounce/GetNounceQuery";
describe("Protected Partitions", () => {
    let commandBusMock;
    let queryBusMock;
    let mirrorNodeMock;
    let getNounceRequest;
    let handleValidationSpy;
    const transactionId = TransactionIdFixture.create().id;
    beforeEach(() => {
        commandBusMock = createMock();
        queryBusMock = createMock();
        mirrorNodeMock = createMock();
        handleValidationSpy = jest.spyOn(ValidatedRequest, "handleValidation");
        jest.spyOn(LogService, "logError").mockImplementation(() => { });
        Security.commandBus = commandBusMock;
        Security.queryBus = queryBusMock;
        Security.mirrorNode = mirrorNodeMock;
    });
    afterEach(() => {
        jest.resetAllMocks();
        jest.restoreAllMocks();
    });
    describe("protectPartitions", () => {
        const partitionsProtectedRequest = new PartitionsProtectedRequest(PartitionsProtectedRequestFixture.create());
        const expectedResponse = {
            payload: true,
            transactionId: transactionId,
        };
        it("should protect partitions successfully", async () => {
            commandBusMock.execute.mockResolvedValue(expectedResponse);
            const result = await Security.protectPartitions(partitionsProtectedRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith("PartitionsProtectedRequest", partitionsProtectedRequest);
            expect(commandBusMock.execute).toHaveBeenCalledWith(new ProtectPartitionsCommand(partitionsProtectedRequest.securityId));
            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(Security.protectPartitions(partitionsProtectedRequest)).rejects.toThrow("Command execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith("PartitionsProtectedRequest", partitionsProtectedRequest);
            expect(commandBusMock.execute).toHaveBeenCalledWith(new ProtectPartitionsCommand(partitionsProtectedRequest.securityId));
        });
        it("should throw error if securityId is invalid", async () => {
            const partitionsProtectedRequest = new PartitionsProtectedRequest({
                ...PartitionsProtectedRequestFixture.create({
                    securityId: "invalid",
                }),
            });
            await expect(Security.protectPartitions(partitionsProtectedRequest)).rejects.toThrow(ValidationError);
        });
    });
    describe("unprotectPartitions", () => {
        const partitionsProtectedRequest = new PartitionsProtectedRequest(PartitionsProtectedRequestFixture.create());
        const expectedResponse = {
            payload: true,
            transactionId: transactionId,
        };
        it("should protect partitions successfully", async () => {
            commandBusMock.execute.mockResolvedValue(expectedResponse);
            const result = await Security.unprotectPartitions(partitionsProtectedRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith("PartitionsProtectedRequest", partitionsProtectedRequest);
            expect(commandBusMock.execute).toHaveBeenCalledWith(new UnprotectPartitionsCommand(partitionsProtectedRequest.securityId));
            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(Security.unprotectPartitions(partitionsProtectedRequest)).rejects.toThrow("Command execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith("PartitionsProtectedRequest", partitionsProtectedRequest);
            expect(commandBusMock.execute).toHaveBeenCalledWith(new UnprotectPartitionsCommand(partitionsProtectedRequest.securityId));
        });
        it("should throw error if securityId is invalid", async () => {
            const partitionsProtectedRequest = new PartitionsProtectedRequest({
                ...PartitionsProtectedRequestFixture.create({
                    securityId: "invalid",
                }),
            });
            await expect(Security.unprotectPartitions(partitionsProtectedRequest)).rejects.toThrow(ValidationError);
        });
    });
    describe("arePartitionsProtected", () => {
        const partitionsProtectedRequest = new PartitionsProtectedRequest(PartitionsProtectedRequestFixture.create());
        const expectedResponse = {
            payload: true,
        };
        it("should check are partitions protected successfully", async () => {
            queryBusMock.execute.mockResolvedValue(expectedResponse);
            const result = await Security.arePartitionsProtected(partitionsProtectedRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith("PartitionsProtectedRequest", partitionsProtectedRequest);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new PartitionsProtectedQuery(partitionsProtectedRequest.securityId));
            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(Security.arePartitionsProtected(partitionsProtectedRequest)).rejects.toThrow("Query execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith("PartitionsProtectedRequest", partitionsProtectedRequest);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new PartitionsProtectedQuery(partitionsProtectedRequest.securityId));
        });
        it("should throw error if securityId is invalid", async () => {
            const partitionsProtectedRequest = new PartitionsProtectedRequest({
                ...PartitionsProtectedRequestFixture.create({
                    securityId: "invalid",
                }),
            });
            await expect(Security.arePartitionsProtected(partitionsProtectedRequest)).rejects.toThrow(ValidationError);
        });
    });
    describe("getNounce", () => {
        getNounceRequest = new GetNounceRequest(GetNounceRequestFixture.create());
        const expectedResponse = {
            payload: 1,
        };
        it("should get nonce successfully", async () => {
            queryBusMock.execute.mockResolvedValue(expectedResponse);
            const result = await Security.getNounce(getNounceRequest);
            expect(handleValidationSpy).toHaveBeenCalledWith("GetNounceRequest", getNounceRequest);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetNounceQuery(getNounceRequest.securityId, getNounceRequest.targetId));
            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(Security.getNounce(getNounceRequest)).rejects.toThrow("Query execution failed");
            expect(handleValidationSpy).toHaveBeenCalledWith("GetNounceRequest", getNounceRequest);
            expect(queryBusMock.execute).toHaveBeenCalledWith(new GetNounceQuery(getNounceRequest.securityId, getNounceRequest.targetId));
        });
        it("should throw error if securityId is invalid", async () => {
            getNounceRequest = new GetNounceRequest({
                ...GetNounceRequestFixture.create({
                    securityId: "invalid",
                }),
            });
            await expect(Security.getNounce(getNounceRequest)).rejects.toThrow(ValidationError);
        });
        it("should throw error if targetId is invalid", async () => {
            getNounceRequest = new GetNounceRequest({
                ...GetNounceRequestFixture.create({
                    targetId: "invalid",
                }),
            });
            await expect(Security.getNounce(getNounceRequest)).rejects.toThrow(ValidationError);
        });
    });
});
