import React from 'react';
import { screen } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import { useContractLabelTerms } from 'src/apollo/queries/contract';
import { ABACUS_PROFILE } from 'src/constants';
import TransferTermsSection from '../transfer-detail/transfer-terms-section';
import type { TransferTerm } from 'src/apollo/queries/transfer-terms';

jest.mock('src/apollo/queries/stores', () => ({
    useStoreList: () => ({ data: { deliveryStoresV2: { items: [] } } }),
}));

// Two presentational groups: Digital (tt-1, tt-2) and Physical (tt-3).
const TXN_GROUPS = [
    {
        referenceTransactionTypeGroupId: 'g-digital',
        transactionTypeGroupName: 'Digital',
        transactionTypes: [{ txnTypeId: 'tt-1' }, { txnTypeId: 'tt-2' }],
    },
    {
        referenceTransactionTypeGroupId: 'g-physical',
        transactionTypeGroupName: 'Physical',
        transactionTypes: [{ txnTypeId: 'tt-3' }],
    },
];

jest.mock('src/apollo/queries/transaction-types', () => ({
    useTransactionTypes: () => ({ data: { transactionTypes: [] } }),
    useTransactionTypeGroups: () => ({
        data: { transactionTypeGroups: TXN_GROUPS },
        loading: false,
    }),
}));

jest.mock('src/apollo/queries/contract', () => ({
    useContractLabelTerms: jest.fn(() => ({ labelTerms: [], loading: false })),
}));

const mockUseContractLabelTerms = useContractLabelTerms as jest.Mock;

const identity = createIdentity({ profileType: ABACUS_PROFILE });

const condition = {
    projectTransferTermConditionId: 'cond-1',
    termRate: 100,
    conditions: { transactionTypes: [], stores: [], countries: [] },
};

const makeTerm = (overrides: Partial<TransferTerm>): TransferTerm => ({
    projectTransferTermId: 'term-1',
    name: null,
    termType: 'product',
    contractId: 'contract-1',
    attachments: [],
    conditions: [condition],
    ...overrides,
});

const labelTermWith = (
    conditions: {
        contractTermConditionId: string;
        termRate: number;
        conditions: { transactionTypes: string[] };
    }[]
) => ({
    labelTerms: [
        {
            contractTermId: 'ct-1',
            contractTermName: 'Label Term',
            termType: 'label',
            conditions: conditions.map(c => ({
                ...c,
                conditions: {
                    countries: [],
                    stores: [],
                    ...c.conditions,
                },
            })),
        },
    ],
    loading: false,
});

beforeEach(() => {
    mockUseContractLabelTerms.mockReturnValue({
        labelTerms: [],
        loading: false,
    });
});

describe('TransferTermsSection', () => {
    it('consolidates label-term conditions into presentational groups', () => {
        mockUseContractLabelTerms.mockReturnValue(
            labelTermWith([
                // Digital spans two rates -> "Multiple Rates"
                {
                    contractTermConditionId: 'c1',
                    termRate: 85,
                    conditions: { transactionTypes: ['tt-1'] },
                },
                {
                    contractTermConditionId: 'c2',
                    termRate: 70,
                    conditions: { transactionTypes: ['tt-2'] },
                },
                // Physical has a single rate
                {
                    contractTermConditionId: 'c3',
                    termRate: 80,
                    conditions: { transactionTypes: ['tt-3'] },
                },
            ])
        );

        renderInAppContext(
            <TransferTermsSection
                terms={[
                    makeTerm({ termType: 'product', attachments: ['123'] }),
                ]}
            />,
            { identity }
        );

        expect(screen.getByText('Terms to be applied')).toBeInTheDocument();
        expect(screen.getByText('Label Terms')).toBeInTheDocument();
        expect(screen.getByText('Term ID: ct-1')).toBeInTheDocument();
        expect(
            screen.getByText('Digital • Multiple Rates, Expand for Details')
        ).toBeInTheDocument();
        expect(screen.getByText('Physical • 80%')).toBeInTheDocument();
        expect(screen.getByText('Product Terms')).toBeInTheDocument();
        // Transfer term ids are temporary (pre-transfer); don't show them.
        expect(screen.getByText('1 Product')).toBeInTheDocument();
        expect(
            screen.queryByText('1 Product • term-1')
        ).not.toBeInTheDocument();
    });

    it('renders an empty Label Terms block when the contract has no label terms', () => {
        renderInAppContext(
            <TransferTermsSection terms={[makeTerm({ termType: 'track' })]} />,
            { identity }
        );

        expect(screen.getByText('Label Terms')).toBeInTheDocument();
        expect(
            screen.getByText(
                'No Label Terms have been defined for this transfer.'
            )
        ).toBeInTheDocument();
        expect(screen.getByText('Track Terms')).toBeInTheDocument();
    });

    it('consolidates product-term conditions into presentational groups too', () => {
        renderInAppContext(
            <TransferTermsSection
                terms={[
                    makeTerm({
                        termType: 'product',
                        conditions: [
                            {
                                projectTransferTermConditionId: 'pc-1',
                                termRate: 70,
                                conditions: {
                                    transactionTypes: ['tt-1'],
                                    stores: [],
                                    countries: [],
                                },
                            },
                        ],
                    }),
                ]}
            />,
            { identity }
        );

        expect(screen.getByText('Digital • 70%')).toBeInTheDocument();
    });

    it('shows the destination-contract alert when there are no terms', () => {
        renderInAppContext(
            <TransferTermsSection terms={[]} contractName="My Contract" />,
            { identity }
        );

        expect(
            screen.getByText(/will apply to all products and tracks/)
        ).toBeInTheDocument();
    });
});
