import React from 'react';
import * as apollo from '@apollo/client';
import { screen, fireEvent, waitFor } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import * as suiteComponents from '@theorchard/suite-components';
import * as profitCenterMutation from 'src/apollo/mutations/reference-sap-profit-center';
import {
    ReferenceSapProfitCenterForm,
    ReferenceSapProfitCenterFormPropTypes,
} from 'src/components/reference-sap-profit-center-create/reference-sap-profit-center-form';

describe('ReferenceSapProfitCenterForm Container Component', () => {
    const addToastMock = jest.fn();
    const mockAddSapProfitCenter = jest.fn().mockResolvedValue({});
    const mockEvict = jest.fn();

    const defaultProps = {
        isSidecarOpen: true,
        setIsSidecarOpen: jest.fn(),
        setPage: jest.fn(),
    };

    beforeEach(() => {
        jest.spyOn(suiteComponents, 'useToast').mockReturnValue(addToastMock);
        jest.spyOn(
            profitCenterMutation,
            'useCreateSapProfitCenter'
        ).mockReturnValue(mockAddSapProfitCenter);
        jest.spyOn(apollo, 'useApolloClient').mockReturnValue({
            cache: { evict: mockEvict },
        } as unknown as apollo.ApolloClient<object>);
    });

    afterEach(() => jest.clearAllMocks());

    const renderComponent = (
        props: ReferenceSapProfitCenterFormPropTypes = defaultProps
    ) => renderInAppContext(<ReferenceSapProfitCenterForm {...props} />);

    it('renders the Sidecar and form fields when open', () => {
        renderComponent();
        expect(screen.getByTestId('ProfitCenterFormSidecar')).toBeDefined();

        expect(screen.getByText('Display Name')).toBeDefined();
        expect(screen.getByText('Profit Center')).toBeDefined();
        expect(screen.getByText('Company Code')).toBeDefined();
        expect(screen.getByText('Business Group')).toBeDefined();
        expect(screen.getByText('Signing Entity')).toBeDefined();
    });

    it('keeps the confirm button disabled until all fields are filled', () => {
        renderComponent();
        const confirmBtn = screen.getByText('Create');

        expect(confirmBtn).toBeDisabled();
    });

    it('successfully processes form submission, handles cache cleanup, and shifts page states', async () => {
        renderComponent();

        const confirmBtn = screen.getByText('Create');
        fireEvent.change(screen.getByTestId('displayName'), {
            target: { value: 'Test Display' },
        });
        fireEvent.change(screen.getByTestId('profitCenter'), {
            target: { value: 'PC1' },
        });
        fireEvent.change(screen.getByTestId('companyCode'), {
            target: { value: 'CC1' },
        });
        fireEvent.change(screen.getByTestId('businessGroup'), {
            target: { value: 'BG1' },
        });

        expect(confirmBtn).not.toBeDisabled();

        fireEvent.click(confirmBtn);
        expect(screen.getByText('Creating...')).toBeDefined();

        await waitFor(() => {
            expect(mockAddSapProfitCenter).toHaveBeenCalledWith({
                variables: {
                    businessGroup: 'BG1',
                    companyCode: 'CC1',
                    displayName: 'Test Display',
                    profitCenter: 'PC1',
                },
            });
            expect(defaultProps.setIsSidecarOpen).toHaveBeenCalledWith(false);
            expect(addToastMock).toHaveBeenCalledWith(
                'Profit center Test Display created successfully.'
            );
            expect(defaultProps.setPage).toHaveBeenCalledWith(0);
            expect(mockEvict).toHaveBeenCalledWith({
                id: 'ROOT_QUERY',
                fieldName: 'abacusReferenceSapProfitCenterList',
            });
        });
    });

    it('handles submission rejections and populates user error states properly', async () => {
        const networkErrorMsg = 'duplicate profit center';
        const mockAddSapProfitCenter = jest
            .fn()
            .mockRejectedValueOnce(networkErrorMsg);
        jest.spyOn(
            profitCenterMutation,
            'useCreateSapProfitCenter'
        ).mockReturnValue(mockAddSapProfitCenter);
        renderComponent();

        const confirmBtn = screen.getByText('Create');
        fireEvent.change(screen.getByTestId('displayName'), {
            target: { value: 'Test Display' },
        });
        fireEvent.change(screen.getByTestId('profitCenter'), {
            target: { value: 'PC1' },
        });
        fireEvent.change(screen.getByTestId('companyCode'), {
            target: { value: 'CC1' },
        });
        fireEvent.change(screen.getByTestId('businessGroup'), {
            target: { value: 'BG1' },
        });

        expect(confirmBtn).not.toBeDisabled();

        fireEvent.click(confirmBtn);
        expect(screen.getByText('Creating...')).toBeDefined();

        await waitFor(() => {
            expect(mockAddSapProfitCenter).toHaveBeenCalledWith({
                variables: {
                    businessGroup: 'BG1',
                    companyCode: 'CC1',
                    displayName: 'Test Display',
                    profitCenter: 'PC1',
                },
            });
            expect(defaultProps.setIsSidecarOpen).not.toHaveBeenCalled();
            expect(addToastMock).not.toHaveBeenCalled();
            expect(defaultProps.setPage).not.toHaveBeenCalled();
            expect(mockEvict).not.toHaveBeenCalled();
            expect(screen.getByTestId('Alert')).toBeDefined();
        });
    });

    it('closes the sidecar successfully if no active asynchronous processes are taking place', () => {
        renderComponent();
        const profitCenterSidecar = screen.getByTestId(
            'ProfitCenterFormSidecar'
        );
        expect(profitCenterSidecar).toBeDefined();

        fireEvent.click(screen.getByText('cancel'));
        expect(defaultProps.setIsSidecarOpen).toHaveBeenCalledWith(false);
    });
});
