import React from 'react';
import { screen, fireEvent } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import { contractDetails as ContractResponse } from 'src/__fixtures__/graphql/contract-details';
import ContractGeneralDetailSection, {
    ContractGeneralDetailSectionPropType,
} from 'src/components/contract-detail/contract-general-detail-section';
import { ABACUS_PROFILE, CONTRACT_TYPES, USER_FEATURES } from 'src/constants';
import { ContractLifecycleContext } from 'src/contexts/contract-lifecycle-context';
import type { AbacusContract } from 'src/types/abacus-contract';

describe('<ContractGeneralDetailSection>', () => {
    const {
        account,
        contractName,
        contractType,
        initialStartDate,
        runController: { runControllerName, runControllerId },
        referenceSigningEntity: { legalName },
        isExcludedFromAccountingRun,
        executionDate,
    } = ContractResponse.abacusContract;

    const defaultProps = {
        account,
        contractName,
        contractType,
        initialStartDate,
        runControllerName,
        runControllerId: String(runControllerId),
        referenceSigningEntityName: legalName,
        isExcludedFromAccountingRun,
        isPaythroughContract: false,
        executionDate,
    };

    const mockFeatures = {
        [USER_FEATURES.ABACUS_PRIMARY_CONTRACT]: false,
    };

    const contractContext = {
        contract: ContractResponse.abacusContract as unknown as AbacusContract,
        isEditingContractRenewalRules: false,
        setIsEditingContractRenewalRules: jest.fn(),
        isTerminatingContract: false,
        setIsTerminatingContract: jest.fn(),
        setContractLifecycle: jest.fn(),
    };

    const renderComponent = (
        props: ContractGeneralDetailSectionPropType = defaultProps,
        features: { [x: number]: boolean } = mockFeatures
    ) =>
        renderInAppContext(
            <ContractLifecycleContext.Provider value={contractContext}>
                <ContractGeneralDetailSection {...props} />
            </ContractLifecycleContext.Provider>,
            {
                identity: createIdentity({
                    features,
                    profileType: ABACUS_PROFILE,
                    id: 'Jane User',
                }),
            }
        );

    it('renders', () => {
        const { container } = renderComponent(defaultProps);
        expect(container).toBeDefined();
    });

    it('displays account name', async () => {
        const updatedProps = {
            ...defaultProps,
            account: {
                ...defaultProps.account,
                accountName: '(SME France) SOULMATES',
            },
        };

        renderComponent(updatedProps);

        const accountName = screen.getByTestId('account-info-name');
        expect(accountName.textContent).toContain('(SME France) SOULMATES');
    });

    it('displays account id', async () => {
        const updatedProps = {
            ...defaultProps,
            account: {
                ...defaultProps.account,
                accountName: '(SME France) SOULMATES',
            },
        };

        renderComponent(updatedProps);

        const accountName = screen.getByTestId('account-info-id');
        expect(accountName.textContent).toContain('25153');
    });

    it('displays paid by', async () => {
        renderComponent(defaultProps);
        expect(screen.getByText('AWAL-UK')).toBeDefined();
    });

    it('displays hyphen for paid by when payment entity is null', async () => {
        const updatedProps = {
            ...defaultProps,
            account: {
                ...defaultProps.account,
                accountPaymentTerm: {
                    ...defaultProps.account.accountPaymentTerm,
                    paymentEntity: null,
                },
            },
        };
        renderComponent(updatedProps);
        const paidBy = screen.getByTestId('account-info-paid-by');
        expect(paidBy.textContent).toContain('-');
    });

    it('displays run controller name', async () => {
        renderComponent(defaultProps);
        const runControllerName = await screen.findByText('See Controller Run');
        expect(runControllerName).toBeDefined();
    });

    it('displays contract type', () => {
        renderComponent(defaultProps);
        expect(screen.getByText('Distribution')).toBeDefined();
    });

    it('hides "OA Contract Status" and "OA Contract ID" fields for NR contract', () => {
        renderComponent({
            ...defaultProps,
            contractType: CONTRACT_TYPES.NEIGHBOURING_RIGHTS,
        });
        expect(screen.queryByText('OA Contract Id')).toBeNull();
        expect(screen.queryByText('OA Contract Status')).toBeNull();
    });

    it('displays initial period start date', async () => {
        renderComponent(defaultProps);
        const initialPeriodStartDate = await screen.findByText('2023-12-31');
        expect(initialPeriodStartDate).toBeDefined();
    });

    it('displays hyphen when no initial period start date', async () => {
        const updatedProps = {
            ...defaultProps,
            executionDate: '2024-07-31',
            initialStartDate: null,
        };
        renderComponent(updatedProps);
        expect(screen.getByText('-')).toBeDefined();
    });

    it('displays included from accounting run', () => {
        renderComponent(defaultProps);
        expect(screen.getByText('Included')).toBeDefined();
    });

    it('displays excluded from accounting run', () => {
        const updatedProps = {
            ...defaultProps,
            isExcludedFromAccountingRun: true,
        };
        renderComponent(updatedProps);
        expect(screen.getByText('Excluded')).toBeDefined();
    });

    it('displays hyphen when no execution date', () => {
        const updatedProps = {
            ...defaultProps,
            executionDate: null,
        };
        renderComponent(updatedProps);
        expect(screen.getByText('-')).toBeDefined();
    });

    it('displays execution date', () => {
        const updatedProps = {
            ...defaultProps,
            executionDate: '2024-07-31',
        };
        renderComponent(updatedProps);
        expect(screen.getByText('2024-07-31')).toBeDefined();
    });

    it('displays an edit icon for contract general information', () => {
        const updatedProps = {
            ...defaultProps,
            executionDate: '2024-07-31',
        };
        renderComponent(updatedProps);
        expect(screen.getAllByTestId('EditGlyphIcon').length).toBeGreaterThan(
            0
        );
    });

    it('opens the sidecar on click of edit icon', () => {
        const updatedProps = {
            ...defaultProps,
            executionDate: '2024-07-31',
        };
        renderComponent(updatedProps);
        const editIcon = screen.getAllByTestId('EditGlyphIcon')[0];
        fireEvent.click(editIcon);
        expect(screen.getByText('General Information')).toBeDefined();
    });

    it('displays "No" for flowthrough contract when isPaythroughContract is false', () => {
        renderComponent(defaultProps);
        expect(screen.getByText('Flowthrough Contract')).toBeDefined();
        expect(screen.getByText('No')).toBeDefined();
    });

    it('displays "Yes" for flowthrough contract when isPaythroughContract is true', () => {
        const updatedProps = {
            ...defaultProps,
            isPaythroughContract: true,
        };
        renderComponent(updatedProps);
        expect(screen.getByText('Flowthrough Contract')).toBeDefined();
        expect(screen.getByText('Yes')).toBeDefined();
    });

    it('hides "Is Primary Contract" field if ff is disabled', () => {
        const updatedProps = {
            ...defaultProps,
            isPrimaryContract: true,
        };
        renderComponent(updatedProps);
        expect(screen.queryByText('Is Primary Contract')).toBeNull();
    });

    it('displays "Yes" for primary contract when isPrimaryContract is true and FF is enabled', () => {
        const updatedProps = {
            ...defaultProps,
            isPrimaryContract: true,
        };
        const enabledFeatures = {
            [USER_FEATURES.ABACUS_PRIMARY_CONTRACT]: true,
        };
        renderComponent(updatedProps, enabledFeatures);
        expect(screen.getByText('Is Primary Contract')).toBeDefined();
        expect(screen.getByText('Yes')).toBeDefined();
    });

    it('displays "No" for primary contract when isPrimaryContract is false and FF is enabled', () => {
        const updatedProps = {
            ...defaultProps,
            isPaythroughContract: true,
            isPrimaryContract: false,
        };
        const enabledFeatures = {
            [USER_FEATURES.ABACUS_PRIMARY_CONTRACT]: true,
        };
        renderComponent(updatedProps, enabledFeatures);
        expect(screen.getByText('Is Primary Contract')).toBeDefined();
        expect(screen.getByText('No')).toBeDefined();
    });

    it('hides "Is Primary Contract" field if ff is enabled and contract is KNR', () => {
        const updatedProps = {
            ...defaultProps,
            contractType: CONTRACT_TYPES.NEIGHBOURING_RIGHTS,
        };
        const enabledFeatures = {
            [USER_FEATURES.ABACUS_PRIMARY_CONTRACT]: true,
        };
        renderComponent(updatedProps, enabledFeatures);
        expect(screen.queryByText('Is Primary Contract')).toBeNull();
    });

    describe('SAP Profit Center field', () => {
        const ffOnFeatures = {
            ...mockFeatures,
            [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: true,
        };
        const ffOffFeatures = {
            ...mockFeatures,
            [USER_FEATURES.ABACUS_SINGLE_SUPPLY_CHAIN_COMPANY_CODES]: false,
        };

        it('displays the SAP Profit Center display name when FF is enabled', () => {
            renderComponent(
                {
                    ...defaultProps,
                    sapProfitCenterDisplayName: 'UK Music Co',
                },
                ffOnFeatures
            );
            expect(screen.getByText('SAP Profit Center')).toBeDefined();
            expect(screen.getByText('UK Music Co')).toBeDefined();
        });

        it('renders a hyphen when FF is enabled but value is missing', () => {
            renderComponent(
                {
                    ...defaultProps,
                    sapProfitCenterDisplayName: null,
                },
                ffOnFeatures
            );
            expect(screen.getByText('SAP Profit Center')).toBeDefined();
            // Two hyphens are present in the section ("Paid By" can also be "-").
            // Locate by label proximity instead.
            const labels = screen.getAllByText('-');
            expect(labels.length).toBeGreaterThan(0);
        });

        it('hides the SAP Profit Center field when FF is disabled', () => {
            renderComponent(
                {
                    ...defaultProps,
                    sapProfitCenterDisplayName: 'UK Music Co',
                },
                ffOffFeatures
            );
            expect(screen.queryByText('SAP Profit Center')).toBeNull();
            expect(screen.queryByText('UK Music Co')).toBeNull();
        });
    });
});
