import React from 'react';
import { screen, fireEvent, waitFor } from '@testing-library/react';
import { renderInAppContext } from '@theorchard/suite-testing';
import * as contractHooks from 'src/apollo/queries/contract-term';
import { ContractTermsDistroConditionsList } from 'src/components/contract-terms-refactored/contract-terms-distro-conditions-list';
import type { AbacusDistroContractTermCondition } from 'src/types/abacus-contract-term';

describe('<ContractTermsDistroConditionsList />', () => {
    const mockOnConditionsChange = jest.fn();
    const mockSetErrors = jest.fn();
    const mockSetIsSaveDisabled = jest.fn();

    const baseConditions: AbacusDistroContractTermCondition[] = [
        {
            contractTermConditionId: '123456789',
            priority: 1,
            termRate: '10.5',
            conditions: {
                countries: ['US'],
                stores: ['Spotify'],
                transactionTypes: ['CL'],
            },
            contractTermConditionName: null,
            contractTermId: '123456789',
        },
    ];

    const baseProps = {
        termId: '123456789',
        contractTermConditions: baseConditions,
        onConditionsChange: mockOnConditionsChange,
        isLoading: false,
        setErrors: mockSetErrors,
        setIsSaveDisabled: mockSetIsSaveDisabled,
    };

    const render = (props = baseProps) =>
        renderInAppContext(<ContractTermsDistroConditionsList {...props} />);

    beforeEach(() => {
        jest.clearAllMocks();

        jest.spyOn(
            contractHooks,
            'useContractTermsByContractId'
        ).mockReturnValue({
            data: undefined,
            loading: false,
            error: undefined,
            getContractsTermsByContractId: jest.fn(),
        });
    });

    it('renders with initial condition data', () => {
        render();
        expect(screen.getByDisplayValue('10.5')).toBeInTheDocument();
    });

    it('adds a new condition when "+ New Condition" is clicked', () => {
        render();
        const addBtn = screen.getByRole('button', { name: '+ New Condition' });
        fireEvent.click(addBtn);

        expect(mockOnConditionsChange).toHaveBeenCalled();
        const result = mockOnConditionsChange.mock.calls[0][0];
        expect(result.length).toBe(2);
        expect(result[1].priority).toBe(2);
    });

    it('opens "Copy Conditions From..." modal when clicked', () => {
        render();
        const copyBtn = screen.getByText('Copy Conditions From...');
        fireEvent.click(copyBtn);

        expect(screen.getByText('Copy Conditions From...')).toBeInTheDocument();
    });

    it('calls onConditionsChange when input is updated', () => {
        render();
        const input = screen.getByDisplayValue('10.5');
        fireEvent.change(input, { target: { value: '12.34' } });

        const result = mockOnConditionsChange.mock.calls.at(-1)?.[0];
        expect(result?.[0]?.termRate).toBe(12.34);
    });

    it('deletes a condition and falls back to one empty row', () => {
        const twoConditions = [
            ...baseConditions,
            {
                ...baseConditions[0],
                contractTermConditionId: 'cond-002',
                priority: 2,
            },
        ];

        render({
            ...baseProps,
            contractTermConditions: twoConditions,
        });

        const deleteButtons = screen.getAllByTestId(
            'contractTermConditionDeleteIcon'
        );
        expect(deleteButtons.length).toBeGreaterThan(1);

        fireEvent.click(deleteButtons[0]);

        expect(mockOnConditionsChange).toHaveBeenCalled();
        const result = mockOnConditionsChange.mock.calls[0][0];
        expect(result.length).toBe(1);
        expect(result[0].priority).toBe(1);
    });

    it('can show conditions loaded via useEffect when not loading', async () => {
        const newConditions: AbacusDistroContractTermCondition[] = [
            {
                contractTermConditionId: '12345678910',
                priority: 1,
                termRate: '20',
                conditions: {
                    countries: ['UK'],
                    stores: [],
                    transactionTypes: [],
                },
                contractTermConditionName: null,
                contractTermId: '123456789',
            },
        ];

        render({
            ...baseProps,
            contractTermConditions: newConditions,
            isLoading: false,
        });

        await waitFor(() => {
            expect(screen.getByDisplayValue('20')).toBeInTheDocument();
        });
    });
});
