import React from 'react';
import { fireEvent, screen } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import * as abacusReferenceAgreementTypesQuery from 'src/apollo/queries/abacus-reference-agreement-types';
import AgreementTypeDropdown, {
    AgreementTypeDropdownPropTypes,
} from '../agreement-type-dropdown';

describe('<AgreementTypeDropdown> layout', () => {
    const defaultProps = {
        id: 'agreementTypeDropdown',
        onChange: jest.fn(),
        selectedValue: '',
    };

    const render = (props: AgreementTypeDropdownPropTypes) =>
        renderInAppContext(<AgreementTypeDropdown {...props} />);
    beforeEach(() => {
        jest.spyOn(
            abacusReferenceAgreementTypesQuery,
            'useReferenceAgreementTypes'
        ).mockReturnValue({
            data: {
                abacusReferenceAgreementTypes: [
                    {
                        agreementType: 'AWAL Core',
                        referenceAgreementTypeId: '1',
                    },
                    { agreementType: 'AWAL +', referenceAgreementTypeId: '2' },
                    {
                        agreementType: 'AWAL Recordings',
                        referenceAgreementTypeId: '3',
                    },
                ],
            },
            loading: false,
        });
    });

    it('renders', () => {
        const { container } = render(defaultProps);
        expect(container).toBeDefined();
        expect(screen.getByText('Select Agreement Type')).toBeDefined();
    });

    it('renders selected value', () => {
        const props = { ...defaultProps, selectedValue: '2' };
        render(props);
        expect(screen.getByText('AWAL +')).toBeDefined();
    });

    describe('allowedAgreementTypeIds filtering', () => {
        const openDropdown = (container: HTMLElement) => {
            const input = container.querySelector('input');
            if (input) fireEvent.keyDown(input, { key: 'ArrowDown' });
        };

        it('shows all options when allowedAgreementTypeIds is not provided', () => {
            const { container } = render(defaultProps);

            openDropdown(container);

            expect(screen.getByText('AWAL Core')).toBeDefined();
            expect(screen.getByText('AWAL +')).toBeDefined();
            expect(screen.getByText('AWAL Recordings')).toBeDefined();
        });

        it('shows all options when allowedAgreementTypeIds is an empty array', () => {
            const { container } = render({
                ...defaultProps,
                allowedAgreementTypeIds: [],
            });

            openDropdown(container);

            expect(screen.getByText('AWAL Core')).toBeDefined();
            expect(screen.getByText('AWAL +')).toBeDefined();
            expect(screen.getByText('AWAL Recordings')).toBeDefined();
        });

        it('filters options to only allowed ids', () => {
            const { container } = render({
                ...defaultProps,
                allowedAgreementTypeIds: ['1', '3'],
            });

            openDropdown(container);

            expect(screen.getByText('AWAL Core')).toBeDefined();
            expect(screen.queryByText('AWAL +')).toBeNull();
            expect(screen.getByText('AWAL Recordings')).toBeDefined();
        });

        describe('ghost option', () => {
            it('shows selected value as disabled when it is not in allowedAgreementTypeIds', () => {
                const { container } = render({
                    ...defaultProps,
                    selectedValue: '2',
                    allowedAgreementTypeIds: ['1', '3'],
                });

                openDropdown(container);

                const disabledOption = container.querySelector(
                    '.Select__option--is-disabled'
                );

                expect(disabledOption).not.toBeNull();
                expect(disabledOption?.textContent).toContain('AWAL +');
            });

            it('does not mark option as disabled when selectedValue is in allowedAgreementTypeIds', () => {
                const { container } = render({
                    ...defaultProps,
                    selectedValue: '1',
                    allowedAgreementTypeIds: ['1', '3'],
                });

                openDropdown(container);

                const disabledOption = container.querySelector(
                    '.Select__option--is-disabled'
                );
                expect(disabledOption).toBeNull();
            });

            it('does not add ghost option when allowedAgreementTypeIds is not provided', () => {
                const { container } = render({
                    ...defaultProps,
                    selectedValue: '2',
                });

                openDropdown(container);

                const disabledOption = container.querySelector(
                    '.Select__option--is-disabled'
                );
                expect(disabledOption).toBeNull();
            });
        });
    });

    it('triggers onChange handler', () => {
        const onChangeHandler = jest.fn();
        const props = { ...defaultProps, onChange: onChangeHandler };
        const { container } = render(props);
        const input = container.querySelector('input');

        if (input) {
            fireEvent.keyDown(input, { key: 'ArrowDown' });
            fireEvent.click(screen.getByText('AWAL Recordings'));
        }

        expect(onChangeHandler).toHaveBeenCalledWith(
            { label: 'AWAL Recordings', value: '3' },
            { action: 'select-option' }
        );
    });
});
