import React from 'react';
import { screen, fireEvent } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import mockDate from 'mockdate';
import { contractDetailsKNR } from 'src/__fixtures__/graphql/contract-details';
import { AbacusContractLifecycleStatus } from 'src/apollo/definitions/globalTypes';
import {
    ContractRenewalSectionNR,
    ContractRenewalSectionNRProps,
} from 'src/components/contract-detail/contract-renewal-section-nr';
import { ABACUS_PROFILE } from 'src/constants';
import {
    ContractLifecycleContext,
    ContractLifecycleContextProps,
} from 'src/contexts/contract-lifecycle-context';

// TODO [ACC-9092]: the structure of `contractDetailsKNR.abacusContract` does not
// match the type signature of `ContractLifecycleContextProps['contract']`.
// Need to figure out where to get the correct type and be able to remove
// all the `as unknown as Contract` from this file.
type Contract = ContractLifecycleContextProps['contract'];

describe('<ContractRenewalSectionNR/>', () => {
    const identity = createIdentity({ profileType: ABACUS_PROFILE });

    const defaultProps: ContractRenewalSectionNRProps = {
        classPrefix: '',
    };
    const defaultContext: ContractLifecycleContextProps = {
        contract: contractDetailsKNR.abacusContract as unknown as Contract,
        isEditingContractRenewalRules: false,
        setIsEditingContractRenewalRules: jest.fn(),
        isTerminatingContract: false,
        setIsTerminatingContract: jest.fn(),
        setContractLifecycle: jest.fn(),
    };

    const renderComponent = (
        props: ContractRenewalSectionNRProps = defaultProps,
        contextValues: Partial<ContractLifecycleContextProps> = {}
    ) =>
        renderInAppContext(
            <ContractLifecycleContext.Provider
                value={{
                    ...defaultContext,
                    ...contextValues,
                }}
            >
                <ContractRenewalSectionNR {...props} />
            </ContractLifecycleContext.Provider>,
            { identity }
        );

    afterEach(() => {
        mockDate.reset();
    });

    it('renders', () => {
        mockDate.set('2024-08-09');
        renderComponent();

        const heading = screen.getByText('Renewal & Collection Rules');
        const currentPeriodStartHeading = screen.getByText(
            'Current Period Start Date'
        );
        const currentPeriodEndHeading = screen.getByText(
            'Current Period End Date'
        );
        const terminationNoticePeriodHeading = screen.getByText(
            'Termination Notice Period'
        );
        const collectionPeriodHeading = screen.getByText('Collection Period');
        const currPeriodStart = screen.getByTestId('current-period-start-date');
        const currPeriodEnd = screen.getByTestId('current-period-end-date');
        const terminationNoticePeriod = screen.getByTestId(
            'termination-notice-period'
        );
        const collectionPeriod = screen.getByTestId('collection-period');
        const description = screen.getByTestId('renewal-section-description');

        expect(heading).toBeInTheDocument();
        expect(currentPeriodStartHeading).toBeInTheDocument();
        expect(currentPeriodEndHeading).toBeInTheDocument();
        expect(terminationNoticePeriodHeading).toBeInTheDocument();
        expect(collectionPeriodHeading).toBeInTheDocument();
        expect(currPeriodStart).toHaveTextContent('2024-08-06');
        expect(currPeriodEnd).toHaveTextContent('2025-08-06');
        expect(terminationNoticePeriod).toHaveTextContent('30 Days');
        expect(collectionPeriod).toHaveTextContent('6 Months');
        expect(description).toHaveTextContent(
            'This contract is set to renew on 2025-08-06. When it renews, the new period start date will be 2025-08-07.The contract will be continuously active from then on. The user can choose to cancel the next renewal at any point up until 2025-07-07.'
        );
    });

    it('display hyphen for fields that are null when they are null', () => {
        const contract = contractDetailsKNR.abacusContract;
        const mockContract = {
            ...contract,
            lifecycle: {
                ...contract.lifecycle,
                lifecycleTermEnd: null,
            },
            lifecycleSchedules: [
                {
                    ...contract.lifecycleSchedules[0],
                    collectionPeriodDetail: null,
                    terminationNoticeDetail: null,
                },
            ],
        };
        renderComponent(defaultProps, {
            contract: mockContract as unknown as Contract,
        });

        const currPeriodStart = screen.getByTestId('current-period-start-date');
        const currPeriodEnd = screen.getByTestId('current-period-end-date');
        const terminationNoticePeriod = screen.getByTestId(
            'termination-notice-period'
        );
        const collectionPeriod = screen.getByTestId('collection-period');

        expect(currPeriodStart).toHaveTextContent('2024-08-06');
        expect(currPeriodEnd).toHaveTextContent('-');
        expect(terminationNoticePeriod).toHaveTextContent('-');
        expect(collectionPeriod).toHaveTextContent('-');
    });

    it('renders an edit icon', () => {
        renderComponent();

        const editIcon = screen.getByTestId('EditGlyphIcon');
        expect(editIcon).toBeInTheDocument();
    });

    it('opens the edit sidecar when edit icon is clicked', () => {
        renderComponent();

        const editIcon = screen.getByTestId('EditGlyphIcon');
        fireEvent.click(editIcon);

        const sidecarHeader = screen.getByText('Renewal & Collection Rules');
        expect(sidecarHeader).toBeInTheDocument();
    });

    it('renders with sidecar already open when specified', () => {
        renderComponent(defaultProps, {
            contract: contractDetailsKNR.abacusContract as unknown as Contract,
            isEditingContractRenewalRules: true,
        });

        const sidecarHeader = screen.getAllByText(
            'Renewal & Collection Rules'
        )[1];
        expect(sidecarHeader).toBeInTheDocument();
    });

    it('disables an edit icon if contract is terminated/to_be_terminated/in_collection_period', () => {
        const contract = contractDetailsKNR.abacusContract;
        const mockContract = {
            ...contract,
            lifecycle: {
                ...contract.lifecycle,
                lifecycleStatus: AbacusContractLifecycleStatus.TERMINATED,
            },
        };
        renderComponent(defaultProps, {
            contract: mockContract as unknown as Contract,
        });

        const editButton = screen.getByRole('button');
        expect(editButton).toBeDisabled();
    });

    it('enables an edit icon if contract is active', () => {
        const contract = contractDetailsKNR.abacusContract;
        const mockContract = {
            ...contract,
            lifecycle: {
                ...contract.lifecycle,
                lifecycleStatus: AbacusContractLifecycleStatus.ACTIVE,
            },
        };
        renderComponent(defaultProps, {
            contract: mockContract as unknown as Contract,
        });

        const editButton = screen.getByRole('button');
        expect(editButton).not.toBeDisabled();
    });
});
