import * as toast from '@theorchard/suite-components';
import { contractFlowthroughDetail } from 'src/__fixtures__/graphql/contract-flowthrough';
import * as abacusCreateContractFlowthrough from 'src/apollo/mutations/contract-flowthrough';
import { useSaveHandler } from '../contract-flowthrough/create-contract-flowthrough';
import type { AbacusContractFlowthroughInput } from 'src/apollo/definitions/globalTypes';

describe('useSaveHandler (create contract flowthrough)', () => {
    let mockCreateContractFlowthrough: jest.Mock;
    let createContractFlowthroughSpy: jest.SpyInstance;
    let useToastSpy: jest.SpyInstance;

    const mockResponse = {
        data: {
            abacusCreateContractFlowthrough: {
                contractFlowthroughId: '123',
            },
        },
    };

    beforeEach(() => {
        mockCreateContractFlowthrough = jest
            .fn()
            .mockResolvedValue(mockResponse);

        createContractFlowthroughSpy = jest
            .spyOn(
                abacusCreateContractFlowthrough,
                'useCreateContractFlowthrough'
            )
            .mockReturnValue(mockCreateContractFlowthrough);

        useToastSpy = jest.spyOn(toast, 'useToast').mockReturnValue(jest.fn());
    });

    afterEach(jest.restoreAllMocks);

    const fixture = contractFlowthroughDetail.abacusContractFlowthrough;

    const contractFlowthrough: Partial<AbacusContractFlowthroughInput> = {
        flowthroughRate: fixture.flowthroughRate,
        contractId: fixture.contract.contractId,
        hasAutomaticShutoff: fixture.hasAutomaticShutoff,
        recoupmentCap: fixture.recoupmentCap,
        calculationComment: fixture.calculationComment,
        referenceFlowthroughCalculationId:
            fixture.referenceFlowthroughCalculation
                .referenceFlowthroughCalculationId,
    };

    it('calls mutation with values from fixture and handles result', async () => {
        const saveHandler = useSaveHandler(fixture.contract.contractId);

        const result = await saveHandler(contractFlowthrough);

        expect(createContractFlowthroughSpy).toHaveBeenCalledWith(
            fixture.contract.contractId
        );
        expect(mockCreateContractFlowthrough).toHaveBeenCalledWith({
            variables: {
                contractFlowthrough: {
                    flowthroughRate: 12.1,
                    contractId: '123',
                    hasAutomaticShutoff: true,
                    recoupmentCap: 12901,
                    calculationComment: 'foo',
                    referenceFlowthroughCalculationId: '1',
                },
            },
        });
        expect(result).toBe('123');
        expect(useToastSpy).toHaveBeenCalled();
    });

    it('sets rate to 0 if not provided', async () => {
        const saveHandler = useSaveHandler(fixture.contract.contractId);

        const result = await saveHandler({
            ...contractFlowthrough,
            flowthroughRate: undefined,
        });

        expect(createContractFlowthroughSpy).toHaveBeenCalledWith(
            fixture.contract.contractId
        );
        expect(mockCreateContractFlowthrough).toHaveBeenCalledWith({
            variables: {
                contractFlowthrough: {
                    flowthroughRate: 0,
                    contractId: '123',
                    hasAutomaticShutoff: true,
                    recoupmentCap: 12901,
                    calculationComment: 'foo',
                    referenceFlowthroughCalculationId: '1',
                },
            },
        });
        expect(result).toBe('123');
        expect(useToastSpy).toHaveBeenCalled();
    });

    it('sets recoupmentCap and calculationComment to null if not provided', async () => {
        const saveHandler = useSaveHandler(fixture.contract.contractId);
        const result = await saveHandler({
            flowthroughRate: 12.1,
            contractId: fixture.contract.contractId,
            hasAutomaticShutoff: true,
            referenceFlowthroughCalculationId:
                fixture.referenceFlowthroughCalculation
                    .referenceFlowthroughCalculationId,
        });
        expect(mockCreateContractFlowthrough).toHaveBeenCalledWith({
            variables: {
                contractFlowthrough: {
                    flowthroughRate: 12.1,
                    contractId: fixture.contract.contractId,
                    hasAutomaticShutoff: true,
                    recoupmentCap: null,
                    calculationComment: null,
                    referenceFlowthroughCalculationId:
                        fixture.referenceFlowthroughCalculation
                            .referenceFlowthroughCalculationId,
                },
            },
        });
        expect(result).toBe('123');
    });

    it('does not call toast if contractFlowthroughId is null', async () => {
        const toastFn = jest.fn();
        useToastSpy.mockReturnValue(toastFn);

        mockCreateContractFlowthrough.mockResolvedValueOnce({
            data: {
                abacusCreateContractFlowthrough: {
                    contractFlowthroughId: null,
                },
            },
        });

        const saveHandler = useSaveHandler(fixture.contract.contractId);
        const result = await saveHandler(contractFlowthrough);

        expect(result).toBe(null);
        expect(toastFn).not.toHaveBeenCalled();
    });
});
