import React from 'react';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import { referenceSigningEntities } from 'src/__fixtures__/graphql/reference-signing-entity';
import * as signingEntitiesQuery from 'src/apollo/queries/reference-signing-entity';
import {
    ReferenceSapProfitCenterFormFields,
    ReferenceSapProfitCenterFormFieldsPropTypes,
} from 'src/components/reference-sap-profit-center-create/reference-sap-profit-center-form-fields';

describe('<ReferenceSapProfitCenterFormFields />', () => {
    beforeEach(() => {
        jest.spyOn(
            signingEntitiesQuery,
            'useReferenceSigningEntities'
        ).mockReturnValue({
            data: referenceSigningEntities,
            loading: false,
            error: undefined,
        });
    });

    beforeEach(() => {
        jest.clearAllMocks();
    });

    const defaultProps: ReferenceSapProfitCenterFormFieldsPropTypes = {
        changeHandler: jest.fn(),
        formData: {
            businessGroup: '',
            companyCode: '',
            displayName: '',
            profitCenter: '',
        },
        error: null,
    };

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

    it('renders form labels', () => {
        renderComponent();

        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('populates fields with initial data passed from formData prop', () => {
        const formData = {
            displayName: 'Test Display Name',
            profitCenter: 'PC123',
            companyCode: 'CC88',
            businessGroup: 'BG1',
            referenceSigningEntityIds: ['1', '4'],
        };

        renderComponent({ ...defaultProps, formData: formData });

        expect(screen.getByTestId('displayName')).toHaveValue(
            'Test Display Name'
        );
        expect(screen.getByTestId('profitCenter')).toHaveValue('PC123');
        expect(screen.getByTestId('companyCode')).toHaveValue('CC88');
        expect(screen.getByTestId('businessGroup')).toHaveValue('BG1');

        expect(screen.getByText('AWAL Digital Limited')).toBeDefined();
    });

    it('triggers changeHandler with correct parameters when display name inputs change', () => {
        renderComponent();

        const displayNameInput = screen.getByTestId('displayName');
        fireEvent.change(displayNameInput, {
            target: { value: 'New Display Name' },
        });
        expect(defaultProps.changeHandler).toHaveBeenCalledWith(
            'displayName',
            'New Display Name'
        );
    });

    it('triggers changeHandler with correct parameters when profit center inputs change', () => {
        renderComponent();

        const profitCenterInput = screen.getByTestId('profitCenter');
        fireEvent.change(profitCenterInput, { target: { value: 'UK999' } });
        expect(defaultProps.changeHandler).toHaveBeenCalledWith(
            'profitCenter',
            'UK999'
        );
    });

    it('triggers changeHandler with correct parameters when company code inputs change', () => {
        renderComponent();

        const companyCodeInput = screen.getByTestId('companyCode');
        fireEvent.change(companyCodeInput, { target: { value: '999' } });
        expect(defaultProps.changeHandler).toHaveBeenCalledWith(
            'companyCode',
            '999'
        );
    });

    it('triggers changeHandler with correct parameters when business group inputs change', () => {
        renderComponent();

        const businessGroupInput = screen.getByTestId('businessGroup');
        fireEvent.change(businessGroupInput, { target: { value: 'ORC' } });
        expect(defaultProps.changeHandler).toHaveBeenCalledWith(
            'businessGroup',
            'ORC'
        );
    });

    it('triggers changeHandler correctly when signing entity selection changes', async () => {
        const expectedOptions =
            referenceSigningEntities.abacusReferenceSigningEntities.items;
        renderComponent();

        const selectButton = screen.getByRole('button');
        fireEvent.click(selectButton);

        await waitFor(() => {
            expect(
                screen.getByText(expectedOptions[0].legalName)
            ).toBeInTheDocument();
        });

        expectedOptions.forEach(option =>
            expect(screen.getByText(option.legalName)).toBeInTheDocument()
        );
        fireEvent.click(screen.getByText(expectedOptions[0].legalName));
        expect(defaultProps.changeHandler).toHaveBeenCalledWith(
            'referenceSigningEntityIds',
            ['4']
        );
    });

    it('enforces character length limits (maxLength) on inputs', () => {
        renderComponent();

        expect(screen.getByTestId('profitCenter')).toHaveAttribute(
            'maxLength',
            '10'
        );
        expect(screen.getByTestId('companyCode')).toHaveAttribute(
            'maxLength',
            '8'
        );
        expect(screen.getByTestId('businessGroup')).toHaveAttribute(
            'maxLength',
            '3'
        );
    });

    it('displays the Alert banner when an error prop is supplied', () => {
        const errorMsg = 'The profit center already exists.';

        renderComponent();
        expect(screen.queryByText(errorMsg)).not.toBeInTheDocument();

        renderComponent({ ...defaultProps, error: errorMsg });

        const alertElement = screen.getByText(errorMsg);
        expect(alertElement).toBeInTheDocument();
        expect(
            alertElement.closest('.SapProfitCenterForm-Error')
        ).toBeInTheDocument();
    });
});
