import React from 'react';
import { fireEvent, screen, waitFor, within } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import {
    mockUseSearchableContractList,
    mockUseContractTermsByContractId,
} from 'src/__fixtures__/graphql/contract-term-hooks';
import { AbacusContractType } from 'src/apollo/definitions/globalTypes';
import { CopyTermConditionsFormPopup } from 'src/components/contract-terms-refactored/contract-terms-distro-copy-terms-popup';

const useParamsMock = jest.fn();
jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    useParams: () => useParamsMock(),
}));

const defaultProps = {
    contractType: AbacusContractType.DISTRIBUTION,
    isCopyConditionsModalOpen: true,
    setIsCopyConditionsModalOpen: jest.fn(),
    conditions: [],
    setConditions: jest.fn(),
};

const renderComponent = (props = {}) =>
    renderInAppContext(
        <CopyTermConditionsFormPopup {...defaultProps} {...props} />
    );

describe('<CopyTermConditionsFormPopup />', () => {
    let searchContractsMock: jest.Mock;

    beforeEach(() => {
        jest.clearAllMocks();
        useParamsMock.mockReturnValue({
            contractTermId: '1234567891011121314',
        });

        searchContractsMock = mockUseSearchableContractList();
        mockUseContractTermsByContractId();
    });

    afterEach(() => {
        jest.useRealTimers();
    });

    it('renders the modal with initial elements when open', () => {
        renderComponent();
        expect(screen.getByTestId('copyConditionsModal')).toBeInTheDocument();
        expect(
            screen.getByText('Copy Conditions From ...')
        ).toBeInTheDocument();
        expect(screen.getByText('Contract')).toBeInTheDocument();
        expect(screen.getByText('Term')).toBeInTheDocument();
        const copyButton = screen.getByRole('button', { name: 'Copy' });
        expect(copyButton).toBeInTheDocument();
        expect(copyButton).toBeDisabled();
        const termSelect = screen.getByTestId(
            'contractTermDistroCopyConditionsHeader'
        );
        expect(
            within(termSelect)
                .getByRole('combobox', { hidden: true })
                .closest('.disabled')
        ).toBeTruthy();
    });

    it('does not render the modal when isCopyConditionsModalOpen is false', () => {
        renderComponent({ isCopyConditionsModalOpen: false });
        expect(
            screen.queryByTestId('copyConditionsModal')
        ).not.toBeInTheDocument();
    });

    it('searches for a contract and displays results', async () => {
        renderComponent();
        const contractField = screen.getByTestId(
            'contractTermDistroCopyConditions'
        );
        fireEvent.click(within(contractField).getByTestId('SuiteSelectInput'));
        const searchInput = await screen.findByRole('textbox');
        fireEvent.input(searchInput, { target: { value: 'Test' } });
        await waitFor(() => {
            expect(searchContractsMock).toHaveBeenCalledWith(
                'test',
                AbacusContractType.DISTRIBUTION
            );
        });
        const option = await screen.findByText(
            'Test Contract Name (12345678910)'
        );
        expect(option).toBeInTheDocument();
    });

    it('populates term multi-select and filters out the current term', async () => {
        renderComponent();
        const contractField = screen.getByTestId(
            'contractTermDistroCopyConditions'
        );
        fireEvent.click(within(contractField).getByTestId('SuiteSelectInput'));
        const searchInput = await screen.findByRole('textbox');
        fireEvent.input(searchInput, { target: { value: 'Test' } });
        fireEvent.click(
            await screen.findByText('Test Contract Name (12345678910)')
        );
        const termSelectField = screen.getByTestId(
            'contractTermDistroCopyConditionsHeader'
        );
        fireEvent.click(
            within(termSelectField).getByTestId('SuiteSelectInput')
        );
        await waitFor(() => {
            expect(
                screen.getByText('First Term - 123456789')
            ).toBeInTheDocument();
        });

        await waitFor(() => {
            expect(screen.getByText('Second Term - T202')).toBeInTheDocument();
        });
        expect(
            screen.queryByText('Current Term - 1234567891011121314')
        ).not.toBeInTheDocument();
    });

    it('enables "Copy" button only after a term is selected', async () => {
        renderComponent();
        const copyButton = screen.getByRole('button', { name: 'Copy' });
        const contractField = screen.getByTestId(
            'contractTermDistroCopyConditions'
        );
        fireEvent.click(within(contractField).getByTestId('SuiteSelectInput'));
        const searchInput = await screen.findByRole('textbox');
        fireEvent.input(searchInput, { target: { value: 'Test' } });
        fireEvent.click(
            await screen.findByText('Test Contract Name (12345678910)')
        );
        expect(copyButton).toBeDisabled();
        const termSelectField = screen.getByTestId(
            'contractTermDistroCopyConditionsHeader'
        );
        fireEvent.click(
            within(termSelectField).getByTestId('SuiteSelectInput')
        );
        fireEvent.click(await screen.findByText('First Term - 123456789'));
        await waitFor(() => {
            expect(copyButton).not.toBeDisabled();
        });
    });

    it('calls setConditions with copied data and closes modal on confirm', async () => {
        const initialConditions = [{ priority: 1, termRate: '5.0' }];
        renderComponent({ conditions: initialConditions });
        const contractField = screen.getByTestId(
            'contractTermDistroCopyConditions'
        );
        fireEvent.click(within(contractField).getByTestId('SuiteSelectInput'));
        const searchInput = await screen.findByRole('textbox');
        fireEvent.input(searchInput, { target: { value: 'Test' } });
        fireEvent.click(
            await screen.findByText('Test Contract Name (12345678910)')
        );
        const termSelectField = screen.getByTestId(
            'contractTermDistroCopyConditionsHeader'
        );
        fireEvent.click(
            within(termSelectField).getByTestId('SuiteSelectInput')
        );
        fireEvent.click(await screen.findByText('First Term - 123456789'));
        const copyButton = screen.getByRole('button', { name: 'Copy' });
        fireEvent.click(copyButton);
        await waitFor(() => {
            expect(defaultProps.setConditions).toHaveBeenCalledWith(
                expect.arrayContaining([
                    initialConditions[0],
                    expect.objectContaining({ priority: 2, termRate: '10.5' }),
                ])
            );
        });
        expect(defaultProps.setIsCopyConditionsModalOpen).toHaveBeenCalledWith(
            false
        );
    });

    it('closes modal and resets state when cancel is clicked', async () => {
        renderComponent();
        const contractField = screen.getByTestId(
            'contractTermDistroCopyConditions'
        );
        fireEvent.click(within(contractField).getByTestId('SuiteSelectInput'));
        const searchInput = await screen.findByRole('textbox');
        fireEvent.input(searchInput, { target: { value: 'Test' } });
        fireEvent.click(
            await screen.findByText('Test Contract Name (12345678910)')
        );
        const termField = screen.getByTestId(
            'contractTermDistroCopyConditionsHeader'
        );
        fireEvent.click(within(termField).getByTestId('SuiteSelectInput'));
        fireEvent.click(await screen.findByText('First Term - 123456789'));

        const termControl = within(termField).getByTestId('SuiteSelectInput');
        const selectedTermTag = within(termControl).getByText(
            'First Term - 123456789'
        );
        expect(selectedTermTag).toBeInTheDocument();

        const cancelButton = screen.getByRole('button', { name: 'Cancel' });
        fireEvent.click(cancelButton);
        expect(defaultProps.setIsCopyConditionsModalOpen).toHaveBeenCalledWith(
            false
        );

        renderComponent();
        expect(
            screen.queryByText('Test Contract Name (12345678910)')
        ).not.toBeInTheDocument();
    });
});
