import React from 'react';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import { accountList } from 'src/__fixtures__/graphql/account-list';
import * as runControllersResponse from 'src/__fixtures__/graphql/contract-run-controller-list-response.json';
import { referenceSigningEntities } from 'src/__fixtures__/graphql/reference-signing-entity';
import { AbacusContractLifecycleStatus } from 'src/apollo/definitions/globalTypes';
import * as accountQuery from 'src/apollo/queries/account';
import * as signingEntitiesQuery from 'src/apollo/queries/reference-signing-entity';
import * as runControllerQuery from 'src/apollo/queries/run-controller';
import {
    TOOLTIP_EXECUTION_DATE,
    PAID_BY_TOOLTIP_MSG,
    PAID_BY_SIGNING_ENTITY_TOOLTIP_MSG,
} from 'src/apollo/type-constants/contract';
import {
    ContractLifecycleGeneralContractInformationScreen,
    ContractLifecycleGeneralContractInformationScreenPropsTypes,
} from 'src/components/contract-lifecycle-create/contract-lifecycle-general-contract-information-screen';
import {
    CONTRACT_TYPES,
    CONTRACT_TYPE_MAP,
    USER_FEATURES,
} from 'src/constants';
import type { Identity } from '@theorchard/suite-frontend';
import type { GetRunControllersQuery } from 'src/apollo/queries/__generated__/run-controller';
import type { AbacusAccountItems } from 'src/apollo/queries/account';
import type { GetAccountsListQuery } from 'src/apollo/queries/account/__generated__/get-accounts-list';

describe('<ContractLifecycleGeneralContractInformationScreen>', () => {
    const defaultProps: ContractLifecycleGeneralContractInformationScreenPropsTypes =
        {
            setContract: jest.fn(),
            contract: {
                accountId: undefined,
                contractName: null,
                contractType: null,
                referencePaymentEntityId: null,
                referenceSigningEntityId: null,
                referenceSapProfitCenterId: null,
                isPrimaryContract: false,
                executionDate: null,
                runControllerId: null,
                generalNote: null,
            },
            contractLifecycleSchedules: [],
            hasCollectionPeriod: false,
            isVisible: true,
            setContractLifecycleSchedules: jest.fn(),
            setExistingPrimaryContract: jest.fn(),
            setHasCollectionPeriod: jest.fn(),
            setModalScreen: jest.fn(),
            setPaymentEntityName: jest.fn(),
            setAccountName: jest.fn(),
            saveHandler: jest.fn(),
        };

    const mockIdentity = {
        features: {
            [USER_FEATURES.ABACUS_PRIMARY_CONTRACT]: false,
            [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: false,
        },
    };

    let accountSearchQueryRequestSpy: jest.SpyInstance;
    let runControllerQuerySpy: jest.SpyInstance;

    beforeEach(() => {
        accountSearchQueryRequestSpy = jest
            .spyOn(accountQuery, 'useAccountSearchQuery')
            .mockReturnValue(
                async () =>
                    await Promise.resolve(
                        accountList.abacusAccounts
                            .items as GetAccountsListQuery['abacusAccounts']['items']
                    )
            );

        jest.spyOn(
            signingEntitiesQuery,
            'useReferenceSigningEntities'
        ).mockReturnValue({
            data: referenceSigningEntities,
            loading: false,
            error: undefined,
        });

        jest.spyOn(
            signingEntitiesQuery,
            'useReferenceSigningEntityFragment'
        ).mockReturnValue(
            referenceSigningEntities.abacusReferenceSigningEntities.items[0]
        );

        runControllerQuerySpy = jest
            .spyOn(runControllerQuery, 'useRunControllerList')
            .mockReturnValue({
                data: runControllersResponse as GetRunControllersQuery,
                loading: false,
                refetch: jest.fn().mockReturnValue(runControllersResponse),
            });
    });

    afterEach(jest.restoreAllMocks);

    const renderComponent = (
        props: ContractLifecycleGeneralContractInformationScreenPropsTypes = defaultProps,
        identity: Partial<Identity> = mockIdentity
    ) =>
        renderInAppContext(
            <ContractLifecycleGeneralContractInformationScreen {...props} />,
            { identity: createIdentity(identity) }
        );

    describe('checks to see if the expected frontend components are present on initial load', () => {
        it('renders each of the form labels', () => {
            renderComponent();
            const selectAccountLabel = screen.getByText('Select Account');
            expect(selectAccountLabel).toBeDefined();
            const contractNameLabel = screen.getByText('Contract Name');
            expect(contractNameLabel).toBeDefined();
            const contractTypeLabel = screen.getByText('Contract Type');
            expect(contractTypeLabel).toBeDefined();
            const signingEntityLabel = screen.getByText('Signing Entity');
            expect(signingEntityLabel).toBeDefined();
            const profitCenterLabel = screen.queryByText('Profit Center Name');
            expect(profitCenterLabel).toBeNull();
            const executionDateLabel = screen.getByText('Execution Date');
            expect(executionDateLabel).toBeDefined();
            const runControllerLabel = screen.getByText('Run Controller');
            expect(runControllerLabel).toBeDefined();
            const primaryContractLabel = screen.queryByText(
                'Is Primary Contract'
            );
            expect(primaryContractLabel).toBeNull();
        });

        it('renders a search dropdown for the select account', () => {
            renderComponent();
            const accountSearchDropdownContainer = screen.getByTestId(
                'accountSearchDropdown'
            );
            expect(accountSearchDropdownContainer).toBeDefined();
            expect(accountSearchDropdownContainer).toHaveTextContent(
                'Search for Accounts'
            );
        });

        it('renders an input field for the contract name', () => {
            renderComponent();
            const contractNameInput = screen.getByTestId('contractNameInput');
            expect(contractNameInput).toBeDefined();
            expect(contractNameInput).toHaveAttribute(
                'placeholder',
                'Enter Contract Name'
            );
        });

        it('sanitizes contract name input by removing newlines, tabs, and returns', () => {
            const setContractMock = jest.fn();
            const props = {
                ...defaultProps,
                setContract: setContractMock,
            };
            renderComponent(props);
            const contractNameInput = screen.getByTestId('contractNameInput');

            fireEvent.change(contractNameInput, {
                target: { name: 'contractName', value: 'Contract\nName' },
            });
            expect(setContractMock).toHaveBeenCalledWith(
                expect.objectContaining({
                    contractName: 'ContractName',
                })
            );

            fireEvent.change(contractNameInput, {
                target: { name: 'contractName', value: 'Contract\tName' },
            });
            expect(setContractMock).toHaveBeenCalledWith(
                expect.objectContaining({
                    contractName: 'ContractName',
                })
            );

            fireEvent.change(contractNameInput, {
                target: { name: 'contractName', value: 'Contract\rName' },
            });
            expect(setContractMock).toHaveBeenCalledWith(
                expect.objectContaining({
                    contractName: 'ContractName',
                })
            );

            fireEvent.change(contractNameInput, {
                target: { name: 'contractName', value: 'My\n\r\tContract' },
            });
            expect(setContractMock).toHaveBeenCalledWith(
                expect.objectContaining({
                    contractName: 'MyContract',
                })
            );

            fireEvent.change(contractNameInput, {
                target: { name: 'contractName', value: 'Normal Contract Name' },
            });
            expect(setContractMock).toHaveBeenCalledWith(
                expect.objectContaining({
                    contractName: 'Normal Contract Name',
                })
            );
        });

        it('renders a dropdown for the contract type', () => {
            renderComponent();
            const contractTypeContainer =
                screen.getByTestId('contractTypeSelect');
            expect(contractTypeContainer).toBeDefined();
            expect(contractTypeContainer).toHaveTextContent(
                'Select Contract Type'
            );
        });

        it('renders a dropdown for signing entity that is initially disabled', () => {
            renderComponent();
            const signingEntityContainer = screen.getByTestId(
                'signingEntitySelect'
            );
            expect(signingEntityContainer).toBeDefined();
            expect(signingEntityContainer).toHaveTextContent(
                'Select Signing Entity'
            );
            const selectInput = screen.getByText(
                'Select Signing Entity'
            ).parentElement!;
            expect(selectInput.className).toContain('disabled');
        });

        it('renders a dropdown for signing entity that is initially disabled and FF is enabled', () => {
            const mockIdentityFFEnabled = {
                features: {
                    [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: true,
                },
            };
            renderComponent(defaultProps, mockIdentityFFEnabled);
            const signingEntityContainer =
                screen.getAllByTestId('SuiteSelectInput')[1];
            expect(signingEntityContainer).toBeDefined();
            expect(signingEntityContainer).toHaveTextContent(
                'Select Signing Entity'
            );
            const selectInput = screen.getByText(
                'Select Signing Entity'
            ).parentElement!;
            expect(selectInput.className).toContain('disabled');
        });

        it('renders a dropdown for run controller that is initially disabled and FF is enabled', () => {
            const mockIdentityFFEnabled = {
                features: {
                    [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: true,
                },
            };
            renderComponent(defaultProps, mockIdentityFFEnabled);
            const runControllerContainer =
                screen.getAllByTestId('SuiteSelectInput')[3];
            expect(runControllerContainer).toBeDefined();
            expect(runControllerContainer).toHaveTextContent('Choose...');
            const selectInput = screen.getByText('Choose...').parentElement!;
            expect(selectInput.className).toContain('disabled');
        });

        it('renders a dropdown for run controller that is initially disabled', () => {
            renderComponent();
            const runControllerContainer = screen.getByTestId(
                'runControllerSelect'
            );
            expect(runControllerContainer).toBeDefined();
            expect(runControllerContainer).toHaveTextContent('Choose...');
            const disabledDropdown =
                runControllerContainer.getElementsByClassName(
                    'Select--is-disabled'
                )[0];
            expect(disabledDropdown).toBeDefined();
        });

        it('does not render the collection period section', () => {
            renderComponent();

            const collectionPeriodSwitch = screen.queryByTestId(
                'collection-period-switch'
            );
            const collectionPeriodInput = screen.queryByTestId(
                'collection-period-interval'
            );
            const collectionPeriodType = screen.queryByTestId(
                'collection-period-type'
            );

            expect(collectionPeriodSwitch).not.toBeInTheDocument();
            expect(collectionPeriodInput).not.toBeInTheDocument();
            expect(collectionPeriodType).not.toBeInTheDocument();
        });

        it('renders the execution date picker and tooltip', async () => {
            renderComponent();
            const executionDatePicker = screen.getByTestId(
                'executionDatePicker'
            );
            expect(executionDatePicker).toBeDefined();
            expect(executionDatePicker).toHaveTextContent('YYYY-MM-DD');

            const toolTip = screen.getByTestId('executionDateTooltip');
            expect(toolTip).toBeDefined();
            fireEvent.mouseOver(toolTip);
            const tooltipText = await screen.findByText(TOOLTIP_EXECUTION_DATE);
            expect(tooltipText).toBeDefined();
        });

        it('renders an add notes button with the expected text', () => {
            renderComponent();
            const addNotesButton = screen.getByTestId('addNotesButton');
            expect(addNotesButton).toBeDefined();
            expect(addNotesButton).toHaveTextContent('+ Add Notes');
        });

        it('renders the next button with the expected text and it is initially disabled', () => {
            renderComponent();
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).toBeDefined();
            expect(nextButton).toHaveTextContent('Continue to Renewal Terms');
            expect(nextButton).toBeDisabled();
        });

        it('does not render the general notes field', () => {
            renderComponent();
            const generalNotesInput = screen.queryByTestId('generalNotesForm');
            expect(generalNotesInput).toBeNull();
        });

        it('hides primary contract switch when FF is disabled and contract type is distribution', () => {
            renderComponent({
                ...defaultProps,
                contract: {
                    ...defaultProps.contract,
                    contractType: CONTRACT_TYPES.DISTRIBUTION,
                },
            });
            expect(screen.queryByText('Is Primary Contract')).toBeNull();
        });

        it('hides primary contract switch when FF is disabled and contract type is NR', () => {
            renderComponent({
                ...defaultProps,
                contract: {
                    ...defaultProps.contract,
                    contractType: CONTRACT_TYPES.NEIGHBOURING_RIGHTS,
                },
            });
            expect(screen.queryByText('Is Primary Contract')).toBeNull();
        });

        it('renders primary contract switch when FF is enabled and contract type is distribution', () => {
            const mockIdentityFFEnabled = {
                features: {
                    [USER_FEATURES.ABACUS_PRIMARY_CONTRACT]: true,
                },
            };
            renderComponent(
                {
                    ...defaultProps,
                    contract: {
                        ...defaultProps.contract,
                        contractType: CONTRACT_TYPES.DISTRIBUTION,
                    },
                },
                mockIdentityFFEnabled
            );
            expect(screen.getByText('Is Primary Contract')).toBeDefined();
        });

        it('renders primary contract switch when FF is enabled and contract type is NR', () => {
            const mockIdentityFFEnabled = {
                features: {
                    [USER_FEATURES.ABACUS_PRIMARY_CONTRACT]: true,
                },
            };
            renderComponent(
                {
                    ...defaultProps,
                    contract: {
                        ...defaultProps.contract,
                        contractType: CONTRACT_TYPES.NEIGHBOURING_RIGHTS,
                    },
                },
                mockIdentityFFEnabled
            );
            expect(screen.queryByText('Is Primary Contract')).toBeNull();
        });
    });

    describe('Account Search and Signing Entity', () => {
        it('renders the account search dropdown with options when the user attempts to search', () => {
            renderComponent();

            const accountSearchDropdownContainer = screen.getByTestId(
                'accountSearchDropdown'
            );
            const accountSearchDropdownInput =
                accountSearchDropdownContainer.getElementsByTagName('input')[0];

            fireEvent.change(accountSearchDropdownInput, {
                target: { value: 'Test Account' },
            });

            const selectedAccount = screen.queryByText('Test Account 1 - 1');
            expect(selectedAccount).toBeDefined();
            expect(accountSearchQueryRequestSpy).toHaveBeenCalled();
        });

        describe('when a user selects an account with an existing payment entity id', () => {
            const mockedAccount = accountList.abacusAccounts.items[0];

            beforeEach(() => {
                jest.spyOn(
                    accountQuery,
                    'useAbacusAccountFragment'
                ).mockReturnValue(mockedAccount as AbacusAccountItems);

                jest.spyOn(
                    signingEntitiesQuery,
                    'useReferenceSigningEntityFragment'
                ).mockReturnValue(null);
            });

            it('renders a paid by label and payment entity name without an auto-populated label', async () => {
                renderComponent();
                const accountSearchDropdownContainer = screen.getByTestId(
                    'accountSearchDropdown'
                );
                const accountSearchDropdownInput =
                    accountSearchDropdownContainer.getElementsByTagName(
                        'input'
                    )[0];
                fireEvent.change(accountSearchDropdownInput, {
                    target: { value: 'Test Account' },
                });

                const selectMenu =
                    accountSearchDropdownContainer.getElementsByClassName(
                        'Select__menu'
                    )[0];
                const selectMenuList =
                    selectMenu.getElementsByClassName('Select__menu-list')[0];
                await waitFor(() => {
                    expect(
                        screen.getByText('Test Account 1 - 1')
                    ).toBeDefined();
                });

                const accountOption =
                    selectMenuList.getElementsByClassName('Select__option')[0];
                expect(accountOption).toBeDefined();
                fireEvent.click(accountOption);
                await waitFor(() => {
                    expect(screen.getByText('Paid By')).toBeDefined();
                });

                const paymentEntityName =
                    screen.getByTestId('paymentEntityName');
                expect(paymentEntityName).toBeDefined();
                expect(paymentEntityName).toHaveTextContent('AWAL-UK');
                expect(
                    screen.queryByText('Auto-Populated')
                ).not.toBeInTheDocument();
            });

            it('renders a help tooltip explaining "paid by"', async () => {
                renderComponent();
                const accountSearchDropdownContainer = screen.getByTestId(
                    'accountSearchDropdown'
                );
                const accountSearchDropdownInput =
                    accountSearchDropdownContainer.getElementsByTagName(
                        'input'
                    )[0];
                fireEvent.change(accountSearchDropdownInput, {
                    target: { value: 'Test Account' },
                });

                const selectMenuList =
                    accountSearchDropdownContainer.getElementsByClassName(
                        'Select__menu-list'
                    )[0];
                let accountOption: Element | null = null;
                await waitFor(() => {
                    accountOption =
                        selectMenuList.getElementsByClassName(
                            'Select__option'
                        )[0];
                    expect(accountOption).toBeDefined();
                });
                if (accountOption) {
                    fireEvent.click(accountOption);
                }

                const paidByHelpTooltip = screen.getByTestId('HelpTooltip');
                expect(paidByHelpTooltip).toBeDefined();
                fireEvent.mouseEnter(paidByHelpTooltip);
                await waitFor(() => {
                    expect(screen.getByText(PAID_BY_TOOLTIP_MSG)).toBeDefined();
                });
            });

            it('enables the signing entity dropdown when an account is selected', async () => {
                renderComponent({
                    ...defaultProps,
                    contract: { ...defaultProps.contract, accountId: '5' },
                });
                const accountSearchDropdownContainer = screen.getByTestId(
                    'accountSearchDropdown'
                );
                const accountSearchDropdownInput =
                    accountSearchDropdownContainer.getElementsByTagName(
                        'input'
                    )[0];
                fireEvent.change(accountSearchDropdownInput, {
                    target: { value: 'Test Account' },
                });

                const selectMenuList =
                    accountSearchDropdownContainer.getElementsByClassName(
                        'Select__menu-list'
                    )[0];
                let accountOption: Element | null =
                    selectMenuList.getElementsByClassName('Select__option')[0];

                await waitFor(() => {
                    accountOption =
                        selectMenuList.getElementsByClassName(
                            'Select__option'
                        )[0];
                    expect(accountOption).toBeDefined();
                });
                if (accountOption) fireEvent.click(accountOption);

                const selectInput = screen.getByText(
                    'Select Signing Entity'
                ).parentElement!;
                expect(selectInput.className).not.toContain('disabled');
            });
        });

        describe('renders sap profit center', () => {
            it('renders the sap profit center dropdown when signing entity is selected and ff is enabled', () => {
                const mockIdentityFFEnabled = {
                    features: {
                        [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: true,
                    },
                };
                renderComponent(
                    {
                        ...defaultProps,
                        contract: {
                            ...defaultProps.contract,
                            referenceSigningEntityId: '6',
                            accountId: '5',
                        },
                    },
                    mockIdentityFFEnabled
                );

                expect(screen.getByText('Profit Center Name')).toBeDefined();

                const profitCenterSelect =
                    screen.getAllByTestId('SuiteSelectInput')[2];
                fireEvent.click(profitCenterSelect);

                expect(
                    screen.getByText(
                        'Kollective Neighbouring Rights Limited : UK4917'
                    )
                ).toBeDefined();
                expect(
                    screen.queryByText(
                        'Kollective Neighbouring Rights Artists B.V. : UK4919'
                    )
                ).toBeNull();
            });

            it('hides the sap profit center dropdown when signing entity is selected and ff is disabled', () => {
                const mockIdentityFFEnabled = {
                    features: {
                        [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: false,
                    },
                };
                renderComponent(
                    {
                        ...defaultProps,
                        contract: {
                            ...defaultProps.contract,
                            referenceSigningEntityId: '6',
                            accountId: '5',
                        },
                    },
                    mockIdentityFFEnabled
                );

                expect(screen.queryByText('Profit Center Name')).toBeNull();
            });

            it('hides the sap profit center dropdown when signing entity is not selected and ff is enabled', () => {
                const mockIdentityFFEnabled = {
                    features: {
                        [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: true,
                    },
                };
                renderComponent(
                    {
                        ...defaultProps,
                        contract: {
                            ...defaultProps.contract,
                            referenceSigningEntityId: null,
                            accountId: '5',
                        },
                    },
                    mockIdentityFFEnabled
                );

                expect(screen.queryByText('Profit Center Name')).toBeNull();
            });
        });

        describe('when a user selects an account without an existing payment entity id', () => {
            const mockedAccount = accountList.abacusAccounts
                .items[2] as AbacusAccountItems;

            beforeEach(() => {
                jest.spyOn(
                    accountQuery,
                    'useAbacusAccountFragment'
                ).mockReturnValue(mockedAccount);

                jest.spyOn(
                    signingEntitiesQuery,
                    'useReferenceSigningEntityFragment'
                ).mockReturnValue(null);
            });

            it('does not render a paid by label and payment entity name', async () => {
                renderComponent();
                const accountSearchDropdownContainer = screen.getByTestId(
                    'accountSearchDropdown'
                );
                const accountSearchDropdownInput =
                    accountSearchDropdownContainer.getElementsByTagName(
                        'input'
                    )[0];
                fireEvent.change(accountSearchDropdownInput, {
                    target: { value: 'Test Account' },
                });

                const selectMenu =
                    accountSearchDropdownContainer.getElementsByClassName(
                        'Select__menu'
                    )[0];

                const selectMenuList =
                    selectMenu.getElementsByClassName('Select__menu-list')[0];
                await waitFor(() => {
                    expect(
                        screen.getByText('Test Account 3 - 3')
                    ).toBeDefined();
                });

                const accountOption =
                    selectMenuList.getElementsByClassName('Select__option')[0];
                expect(accountOption).toBeDefined();
                fireEvent.click(accountOption);
                expect(screen.queryByText('paid by')).toBeNull();
                expect(screen.queryByTestId('paymentEntityName')).toBeNull();
            });

            it('renders an auto-populated highlight and tooltip after the user selects a signing entity', async () => {
                jest.spyOn(
                    signingEntitiesQuery,
                    'useReferenceSigningEntityFragment'
                ).mockReturnValue(
                    referenceSigningEntities.abacusReferenceSigningEntities
                        .items[0]
                );

                // Override the account mock: post-teardown the
                // "shouldUpdatePaymentEntity" effect inspects contract
                // lifecycle status. Mark all contracts as terminated so the
                // signing-entity paid-by tooltip renders.
                jest.spyOn(
                    accountQuery,
                    'useAbacusAccountFragment'
                ).mockReturnValue({
                    ...mockedAccount,
                    contracts: mockedAccount.contracts?.map(c => ({
                        ...c!,
                        lifecycle: {
                            ...c!.lifecycle!,
                            lifecycleStatus:
                                AbacusContractLifecycleStatus.TERMINATED,
                        },
                    })) as typeof mockedAccount.contracts,
                });

                renderComponent({
                    ...defaultProps,
                    contract: {
                        ...defaultProps.contract,
                        accountId: '3',
                        referenceSigningEntityId: '1',
                    },
                });
                const toolTip = screen.getByTestId(
                    'paidBySigningEntityTooltip'
                );
                const autoPopulatedHighlight = screen.getByTestId(
                    'autoPopulatedHighlight'
                );
                expect(toolTip).toBeDefined();
                fireEvent.mouseOver(toolTip);
                const tooltipText = await screen.findByText(
                    PAID_BY_SIGNING_ENTITY_TOOLTIP_MSG
                );
                expect(tooltipText).toBeDefined();
                expect(autoPopulatedHighlight).toBeDefined();
                expect(autoPopulatedHighlight).toHaveTextContent(
                    'Auto-Populated'
                );
            });
        });

        describe('signing entity behavior', () => {
            const identityWithFF = {
                features: {},
            };

            it('renders an auto-populated label when selected account does not have any contracts', async () => {
                const mockAccount = {
                    ...accountList.abacusAccounts.items[0],
                    contracts: [],
                } as AbacusAccountItems;
                jest.spyOn(
                    accountQuery,
                    'useAbacusAccountFragment'
                ).mockReturnValue(mockAccount);

                renderComponent(defaultProps, identityWithFF);
                const accountSearchDropdownContainer = screen.getByTestId(
                    'accountSearchDropdown'
                );
                const accountSearchDropdownInput =
                    accountSearchDropdownContainer.getElementsByTagName(
                        'input'
                    )[0];
                fireEvent.change(accountSearchDropdownInput, {
                    target: { value: 'Test Account' },
                });

                const selectMenu =
                    accountSearchDropdownContainer.getElementsByClassName(
                        'Select__menu'
                    )[0];
                const selectMenuList =
                    selectMenu.getElementsByClassName('Select__menu-list')[0];

                await waitFor(() => {
                    expect(
                        screen.getByText('Test Account 1 - 1')
                    ).toBeInTheDocument();
                });

                const accountOption =
                    selectMenuList.getElementsByClassName('Select__option')[0];
                fireEvent.click(accountOption);

                await waitFor(() => {
                    expect(screen.getByText('Paid By')).toBeInTheDocument();
                });

                expect(
                    screen.getByTestId('autoPopulatedHighlight')
                ).toBeInTheDocument();
            });

            it('renders an auto-populated label when selected account has all terminated contracts', async () => {
                const mockAccount = {
                    ...accountList.abacusAccounts.items[0],
                    contracts: [
                        {
                            ...accountList.abacusAccounts.items[0].contracts[0],
                            lifecycle: {
                                ...accountList.abacusAccounts.items[0]
                                    .contracts[0].lifecycle,
                                lifecycleStatus:
                                    AbacusContractLifecycleStatus.TERMINATED,
                            },
                        },
                    ],
                } as AbacusAccountItems;

                jest.spyOn(
                    accountQuery,
                    'useAbacusAccountFragment'
                ).mockReturnValue(mockAccount);

                renderComponent(defaultProps, identityWithFF);
                const accountSearchDropdownContainer = screen.getByTestId(
                    'accountSearchDropdown'
                );
                const accountSearchDropdownInput =
                    accountSearchDropdownContainer.getElementsByTagName(
                        'input'
                    )[0];
                fireEvent.change(accountSearchDropdownInput, {
                    target: { value: 'Test Account' },
                });

                const selectMenu =
                    accountSearchDropdownContainer.getElementsByClassName(
                        'Select__menu'
                    )[0];
                const selectMenuList =
                    selectMenu.getElementsByClassName('Select__menu-list')[0];

                await waitFor(() => {
                    expect(
                        screen.getByText('Test Account 1 - 1')
                    ).toBeInTheDocument();
                });

                const accountOption =
                    selectMenuList.getElementsByClassName('Select__option')[0];
                fireEvent.click(accountOption);

                await waitFor(() => {
                    expect(screen.getByText('Paid By')).toBeDefined();
                });

                expect(
                    screen.getByTestId('autoPopulatedHighlight')
                ).toBeInTheDocument();
            });

            it('does not render an auto-populated label when selected account has an active contract', async () => {
                const mockAccount = accountList.abacusAccounts
                    .items[0] as AbacusAccountItems;

                jest.spyOn(
                    accountQuery,
                    'useAbacusAccountFragment'
                ).mockReturnValue(mockAccount);

                renderComponent(defaultProps, identityWithFF);
                const accountSearchDropdownContainer = screen.getByTestId(
                    'accountSearchDropdown'
                );
                const accountSearchDropdownInput =
                    accountSearchDropdownContainer.getElementsByTagName(
                        'input'
                    )[0];
                fireEvent.change(accountSearchDropdownInput, {
                    target: { value: 'Test Account' },
                });

                const selectMenu =
                    accountSearchDropdownContainer.getElementsByClassName(
                        'Select__menu'
                    )[0];
                const selectMenuList =
                    selectMenu.getElementsByClassName('Select__menu-list')[0];

                await waitFor(() => {
                    expect(
                        screen.getByText('Test Account 1 - 1')
                    ).toBeInTheDocument();
                });

                const accountOption =
                    selectMenuList.getElementsByClassName('Select__option')[0];
                fireEvent.click(accountOption);

                await waitFor(() => {
                    expect(screen.getByText('Paid By')).toBeDefined();
                });

                expect(
                    screen.queryByTestId('autoPopulatedHighlight')
                ).not.toBeInTheDocument();
            });
        });
    });

    describe('Contract Type and Run Controller', () => {
        it('renders the expected contract type options', () => {
            renderComponent();

            const contractTypeContainer =
                screen.getByTestId('contractTypeSelect');
            const contractTypeInput =
                contractTypeContainer.getElementsByTagName('input')[0];

            fireEvent.change(contractTypeInput, {
                target: { value: ' ' },
            });

            const distroContractType = screen.queryByText(
                CONTRACT_TYPE_MAP.distribution
            );
            const nrContractType = screen.queryByText(
                CONTRACT_TYPE_MAP.neighbouring_rights
            );
            const legacyDistroContractType = screen.queryByText(
                CONTRACT_TYPE_MAP.legacy_distribution
            );

            expect(distroContractType).toBeInTheDocument();
            expect(nrContractType).toBeInTheDocument();
            expect(legacyDistroContractType).not.toBeInTheDocument();
        });

        it('activates the run controller dropdown when a contract type is selected', async () => {
            renderComponent({
                ...defaultProps,
                contract: {
                    ...defaultProps.contract,
                    contractType: CONTRACT_TYPE_MAP.distribution,
                },
            });
            expect(runControllerQuerySpy).toHaveBeenCalled();

            const runControllerContainer = screen.getByTestId(
                'runControllerSelect'
            );
            await waitFor(() => {
                const disabledDropdown =
                    runControllerContainer.getElementsByClassName(
                        'Select--is-disabled'
                    )[0];
                expect(disabledDropdown).toBeUndefined();
            });
        });
    });

    describe('Collection Period', () => {
        it('renders only the collection period switch when the user selects a PNR contract type', () => {
            renderComponent({
                ...defaultProps,
                contract: {
                    ...defaultProps.contract,
                    contractType: 'neighbouring_rights',
                },
            });

            const collectionPeriodSwitch = screen.getByTestId(
                'collection-period-switch'
            );

            expect(collectionPeriodSwitch).toBeInTheDocument();
            expect(collectionPeriodSwitch).not.toBeChecked();
            expect(collectionPeriodSwitch.nextSibling?.textContent).toEqual(
                'There is a collection period'
            );
        });
    });

    describe('General Notes', () => {
        it('renders the general notes field when the user clicks the add notes button and the add notes button disappears', () => {
            renderComponent();

            const addNotesButton = screen.getByTestId('addNotesButton');
            fireEvent.click(addNotesButton);

            const generalNotesInput = screen.getByTestId('generalNotesForm');

            expect(generalNotesInput).toBeDefined();
            expect(generalNotesInput).toHaveAttribute(
                'placeholder',
                'Enter Contract Summary Notes'
            );
            expect(screen.queryByTestId('addNotesButton')).toBeNull();
        });

        it('displays the expected text when the user enters text into the general notes field', () => {
            renderComponent({
                ...defaultProps,
                contract: {
                    ...defaultProps.contract,
                    generalNote: 'test text',
                },
            });
            const generalNotesInput = screen.getByTestId('generalNotesForm');
            expect(generalNotesInput).toHaveValue('test text');
        });
    });

    describe('next button', () => {
        const populatedProps: ContractLifecycleGeneralContractInformationScreenPropsTypes =
            {
                ...defaultProps,
                contract: {
                    accountId: '1',
                    contractName: 'test',
                    contractType: 'distribution',
                    referencePaymentEntityId: null,
                    referenceSigningEntityId: '1',
                    executionDate: '2021-01-01',
                    runControllerId: '1',
                    generalNote: 'test',
                },
            };

        it('is disabled when the accountId is missing', () => {
            renderComponent({
                ...populatedProps,
                contract: { ...populatedProps.contract, accountId: undefined },
            });
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).toBeDisabled();
        });

        it('is disabled when the contractName is missing', () => {
            renderComponent({
                ...populatedProps,
                contract: { ...populatedProps.contract, contractName: null },
            });
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).toBeDisabled();
        });

        it('is disabled when the contractType is missing', () => {
            renderComponent({
                ...populatedProps,
                contract: { ...populatedProps.contract, contractType: null },
            });
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).toBeDisabled();
        });

        it('is disabled when the referenceSigningEntityId is missing', () => {
            renderComponent({
                ...populatedProps,
                contract: {
                    ...populatedProps.contract,
                    referenceSigningEntityId: null,
                },
            });
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).toBeDisabled();
        });

        it('is disabled when the runControllerId is missing', () => {
            renderComponent({
                ...populatedProps,
                contract: { ...populatedProps.contract, runControllerId: null },
            });
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).toBeDisabled();
        });

        it('is disabled when all the contract data is present, but the collection period switch is on and the collectionPeriodDetailInterval is missing', () => {
            renderComponent({
                ...populatedProps,
                hasCollectionPeriod: true,
                contract: {
                    ...populatedProps.contract,
                    contractType: 'neighbouring_rights',
                },
            });

            const collectionPeriodSwitch = screen.getByTestId(
                'collection-period-switch'
            );
            fireEvent.click(collectionPeriodSwitch);

            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).toBeDisabled();
        });

        it('is not disabled when all the contract data is present and collection period switch is on and the collectionPeriodDetailInterval is present', () => {
            renderComponent({
                ...populatedProps,
                hasCollectionPeriod: true,
                contract: {
                    ...populatedProps.contract,
                    contractType: 'neighbouring_rights',
                },
            });

            const collectionPeriodSwitch = screen.getByTestId(
                'collection-period-switch'
            );
            fireEvent.click(collectionPeriodSwitch);

            const collectionPeriodInput = screen
                .getByTestId('collection-period-interval')
                .getElementsByTagName('input')[0];
            fireEvent.change(collectionPeriodInput, {
                target: { value: '1' },
            });

            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).not.toBeDisabled();
        });

        it('is not disabled when only the referencePaymentEntityId is missing', () => {
            renderComponent({
                ...populatedProps,
                contract: {
                    ...populatedProps.contract,
                    referencePaymentEntityId: null,
                },
            });
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).not.toBeDisabled();
        });

        it('is not disabled when only the executionDate is missing', () => {
            renderComponent({
                ...populatedProps,
                contract: { ...populatedProps.contract, executionDate: null },
            });
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).not.toBeDisabled();
        });

        it('is not disabled when only the generalNote is missing', () => {
            renderComponent({
                ...populatedProps,
                contract: { ...populatedProps.contract, generalNote: null },
            });
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).not.toBeDisabled();
        });

        it('renders modal popup if already another primary contract exist and ff is enabled', () => {
            const mockIdentityFFEnabled = {
                features: {
                    [USER_FEATURES.ABACUS_PRIMARY_CONTRACT]: true,
                },
            };
            const mockAccount = accountList.abacusAccounts
                .items[1] as AbacusAccountItems;

            jest.spyOn(
                accountQuery,
                'useAbacusAccountFragment'
            ).mockReturnValue(mockAccount);

            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        accountId: '2',
                        isPrimaryContract: true,
                    },
                },
                mockIdentityFFEnabled
            );
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).not.toBeDisabled();
            fireEvent.click(nextButton);

            expect(
                screen.getByText('Set New Contract as Primary')
            ).toBeDefined();
        });

        it('does not render modal popup if there is no other primary contract and ff is enabled', () => {
            const mockIdentityFFEnabled = {
                features: {
                    [USER_FEATURES.ABACUS_PRIMARY_CONTRACT]: true,
                },
            };
            const mockAccount = accountList.abacusAccounts
                .items[0] as AbacusAccountItems;

            jest.spyOn(
                accountQuery,
                'useAbacusAccountFragment'
            ).mockReturnValue(mockAccount);

            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        isPrimaryContract: true,
                    },
                },
                mockIdentityFFEnabled
            );
            const nextButton = screen.getByTestId('nextButton');
            expect(nextButton).not.toBeDisabled();
            fireEvent.click(nextButton);

            expect(
                screen.queryByText('Set New Contract as Primary')
            ).toBeNull();
        });
    });

    describe('skip button', () => {
        const populatedProps: ContractLifecycleGeneralContractInformationScreenPropsTypes =
            {
                ...defaultProps,
                contract: {
                    accountId: '1',
                    contractName: 'test',
                    contractType: 'distribution',
                    referencePaymentEntityId: null,
                    referenceSigningEntityId: '1',
                    executionDate: '2021-01-01',
                    runControllerId: '1',
                    generalNote: 'test',
                },
            };

        const mockIdentityFFEnabled = {
            features: {
                [USER_FEATURES.ABACUS_PRIMARY_CONTRACT]: true,
            },
        };

        it('is disabled when the accountId is missing', () => {
            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        accountId: undefined,
                    },
                },
                mockIdentityFFEnabled
            );
            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).toBeDisabled();
        });

        it('is disabled when the contractName is missing', () => {
            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        contractName: null,
                    },
                },
                mockIdentityFFEnabled
            );
            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).toBeDisabled();
        });

        it('is disabled when the contractType is missing', () => {
            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        contractType: null,
                    },
                },
                mockIdentityFFEnabled
            );
            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).toBeDisabled();
        });

        it('is disabled when the referenceSigningEntityId is missing', () => {
            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        referenceSigningEntityId: null,
                    },
                },
                mockIdentityFFEnabled
            );
            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).toBeDisabled();
        });

        it('is disabled when the runControllerId is missing', () => {
            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        runControllerId: null,
                    },
                },
                mockIdentityFFEnabled
            );
            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).toBeDisabled();
        });

        it('is disabled when all the contract data is present, but the collection period switch is on and the collectionPeriodDetailInterval is missing', () => {
            renderComponent(
                {
                    ...populatedProps,
                    hasCollectionPeriod: true,
                    contract: {
                        ...populatedProps.contract,
                        contractType: 'neighbouring_rights',
                    },
                },
                mockIdentityFFEnabled
            );

            const collectionPeriodSwitch = screen.getByTestId(
                'collection-period-switch'
            );
            fireEvent.click(collectionPeriodSwitch);

            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).toBeDisabled();
        });

        it('is not disabled when all the contract data is present and collection period switch is on and the collectionPeriodDetailInterval is present', () => {
            renderComponent(
                {
                    ...populatedProps,
                    hasCollectionPeriod: true,
                    contract: {
                        ...populatedProps.contract,
                        contractType: 'neighbouring_rights',
                    },
                },
                mockIdentityFFEnabled
            );

            const collectionPeriodSwitch = screen.getByTestId(
                'collection-period-switch'
            );
            fireEvent.click(collectionPeriodSwitch);

            const collectionPeriodInput = screen
                .getByTestId('collection-period-interval')
                .getElementsByTagName('input')[0];
            fireEvent.change(collectionPeriodInput, {
                target: { value: '1' },
            });

            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).not.toBeDisabled();
        });

        it('is not disabled when only the referencePaymentEntityId is missing', () => {
            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        referencePaymentEntityId: null,
                    },
                },
                mockIdentityFFEnabled
            );
            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).not.toBeDisabled();
        });

        it('is not disabled when only the executionDate is missing', () => {
            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        executionDate: null,
                    },
                },
                mockIdentityFFEnabled
            );
            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).not.toBeDisabled();
        });

        it('is not disabled when only the generalNote is missing', () => {
            renderComponent(
                {
                    ...populatedProps,
                    contract: { ...populatedProps.contract, generalNote: null },
                },
                mockIdentityFFEnabled
            );
            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).not.toBeDisabled();
        });

        it('renders modal popup if already another primary contract exist and ff is enabled', () => {
            const mockAccount = accountList.abacusAccounts
                .items[1] as AbacusAccountItems;

            jest.spyOn(
                accountQuery,
                'useAbacusAccountFragment'
            ).mockReturnValue(mockAccount);

            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        accountId: '2',
                        isPrimaryContract: true,
                    },
                },
                mockIdentityFFEnabled
            );
            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).not.toBeDisabled();
            fireEvent.click(skipButton);

            expect(
                screen.getByText('Set New Contract as Primary')
            ).toBeDefined();
        });

        it('does not render modal popup if there is no other primary contract and ff is enabled', () => {
            const mockAccount = accountList.abacusAccounts
                .items[0] as AbacusAccountItems;

            jest.spyOn(
                accountQuery,
                'useAbacusAccountFragment'
            ).mockReturnValue(mockAccount);

            renderComponent(
                {
                    ...populatedProps,
                    contract: {
                        ...populatedProps.contract,
                        isPrimaryContract: true,
                    },
                },
                mockIdentityFFEnabled
            );
            const skipButton = screen.getByTestId('skipButton');
            expect(skipButton).not.toBeDisabled();
            fireEvent.click(skipButton);

            expect(
                screen.queryByText('Set New Contract as Primary')
            ).toBeNull();
            expect(populatedProps.saveHandler).toHaveBeenCalled();
        });

        describe('Contract Type and Run Controller when FF is enabled', () => {
            it('renders the expected contract type options', () => {
                const mockIdentityFFEnabled = {
                    features: {
                        [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: true,
                    },
                };
                renderComponent(defaultProps, mockIdentityFFEnabled);

                const contractTypeSelect =
                    screen.getAllByTestId('SuiteSelectInput')[0];
                fireEvent.click(contractTypeSelect);
                expect(screen.getByText('Distribution')).toBeDefined();
                expect(
                    screen.getByText('Performer Neighbouring Rights')
                ).toBeDefined();
            });

            it('activates the run controller dropdown when a contract type is selected and FF is enabled', async () => {
                const mockIdentityFFEnabled = {
                    features: {
                        [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: true,
                    },
                };
                renderComponent(
                    {
                        ...defaultProps,
                        contract: {
                            ...defaultProps.contract,
                            contractType: CONTRACT_TYPE_MAP.distribution,
                        },
                    },
                    mockIdentityFFEnabled
                );
                expect(runControllerQuerySpy).toHaveBeenCalled();

                const runControllerSelect =
                    screen.getAllByTestId('SuiteSelectInput')[3];
                expect(runControllerSelect).toBeDefined();
                expect(runControllerSelect).toHaveTextContent('Choose...');
                const selectInput =
                    screen.getByText('Choose...').parentElement!;
                expect(selectInput.className).not.toContain('disabled');
            });
        });
    });
});
