import React from 'react';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { contractFlowthroughDetail } from 'src/__fixtures__/graphql/contract-flowthrough';
import * as updateContractFlowthroughHook from 'src/hooks/contract-flowthrough/update-contract-flowthrough';
import { AbacusContractFlowthrough } from 'src/types/abacus-contract-flowthrough';
import {
    ContractFlowthroughSidecar,
    ContractFlowthroughSidecarProps,
} from '../contract-flowthrough-sidecar';

describe('<ContractFlowthroughSidecar />', () => {
    const defaultProps = {
        isSidecarOpen: true,
        setIsSidecarOpen: jest.fn(),
        contractFlowthrough:
            contractFlowthroughDetail.abacusContractFlowthrough as AbacusContractFlowthrough,
    };

    const render = (props: ContractFlowthroughSidecarProps = defaultProps) => {
        renderInAppContext(<ContractFlowthroughSidecar {...props} />);
    };

    describe('Sidecar rendering', () => {
        it('renders sidecar when isSidecarOpen is true', () => {
            render();
            expect(
                screen.getByTestId('contractFlowthroughSidecar')
            ).toBeDefined();
        });

        it('renders sidecar with correct title', () => {
            render();
            expect(screen.getByText('Flowthrough')).toBeDefined();
        });

        it('does not render sidecar when isSidecarOpen is false', () => {
            render({ ...defaultProps, isSidecarOpen: false });
            expect(
                screen.queryByTestId('contractFlowthroughSidecar')
            ).toBeNull();
        });

        it('calls setIsSidecarOpen when close button is clicked', async () => {
            render();
            const cancelButton = screen.getByText('cancel');
            fireEvent.click(cancelButton);
            await waitFor(() => {
                expect(defaultProps.setIsSidecarOpen).toHaveBeenCalledWith(
                    false
                );
            });
        });
    });

    describe('Save Handler', () => {
        it('displays server error when save handler fails', async () => {
            const mockSaveHandler = jest
                .fn()
                .mockRejectedValue('Server save error');
            jest.spyOn(
                updateContractFlowthroughHook,
                'useSaveHandler'
            ).mockReturnValue(mockSaveHandler);
            render();
            const saveButton = screen.getByText('save');
            fireEvent.click(saveButton);

            const alert = await screen.findByTestId('Alert');

            expect(alert).toHaveTextContent(
                'Error: Server save error, Failed to create contract flowthrough. Please contact the Abacus team'
            );
        });
        it('calls save handler with updated values', async () => {
            const mockSaveHandler = jest.fn().mockResolvedValue({});
            jest.spyOn(
                updateContractFlowthroughHook,
                'useSaveHandler'
            ).mockReturnValue(mockSaveHandler);
            render();

            const flowthroughRateInput = screen.getByTestId(
                'contractFlowthroughRate'
            );
            fireEvent.change(flowthroughRateInput, {
                target: { value: '25' },
            });

            const saveButton = screen.getByText('save');
            fireEvent.click(saveButton);

            expect(mockSaveHandler).toHaveBeenCalledWith(
                expect.objectContaining({
                    flowthroughRate: '25',
                })
            );

            await waitFor(() => {
                expect(defaultProps.setIsSidecarOpen).toHaveBeenCalledWith(
                    false
                );
            });
        });
    });
});
