import React from 'react';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import { ABACUS_PROFILE } from 'src/constants';
import CreateTransferForm from '../create-transfer/create-transfer-form';

// Two accounts and a single (auto-selected) contract, so the only thing left to
// gate the Next button is the project selection.
jest.mock('src/apollo/queries/account', () => ({
    useAccountsForTransferSearch: () => ({
        search: async () => ({
            data: [
                { label: 'From Co', value: 'from-1', subtitle: '101' },
                { label: 'To Co', value: 'to-1', subtitle: '202' },
            ],
            totalCount: 2,
        }),
        getAccount: (id: string) =>
            id === 'from-1'
                ? {
                      accountId: 'from-1',
                      accountName: 'From Co',
                      vendor: { vendorId: 101 },
                  }
                : {
                      accountId: 'to-1',
                      accountName: 'To Co',
                      vendor: { vendorId: 202 },
                  },
    }),
    useAccountContracts: () => ({
        contracts: [
            {
                contractId: 'c-1',
                contractName: 'Contract One',
                contractType: 'Standard',
            },
        ],
    }),
    useAccountSubaccounts: () => ({
        subaccounts: [{ subaccountId: 88046, name: 'Sub A' }],
    }),
}));

// The picker resolves the project, but its product/track tree never arrives:
// allProductsSearch returns no matching product (a settled, empty result — the
// "test project filtered out / index miss" case). Next must NOT depend on it.
jest.mock('src/apollo/queries/product-search', () => ({
    useProjectById: () => jest.fn().mockResolvedValue(null),
    useProjectSearch: () =>
        jest.fn().mockResolvedValue([
            {
                projectId: 42,
                projectName: 'Proj',
                projectCode: 'PC',
                productCount: 1,
                vendorId: 101,
                subaccountId: 88046,
            },
        ]),
    useProjectProducts: () => ({ products: [], loading: false }),
}));

const mockCreate = jest.fn().mockResolvedValue({ projectTransferJobId: 'j-1' });
jest.mock('src/apollo/mutations/create-project-transfer', () => ({
    useCreateProjectTransfer: () => ({ create: mockCreate }),
}));

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

const openAndSelect = async (triggerText: string, optionText: string) => {
    fireEvent.click(screen.getByText(triggerText));
    fireEvent.click(await screen.findByText(optionText));
};

const typeAndSelectProject = async (term: string, optionText: string) => {
    fireEvent.click(screen.getByText('Select Project'));
    fireEvent.change(await screen.findByPlaceholderText('Search project'), {
        target: { value: term },
    });
    fireEvent.click(await screen.findByText(optionText));
};

describe('CreateTransferForm — Next gate', () => {
    it('enables Next once accounts, project and contract are chosen, even when the product tree never resolves', async () => {
        renderInAppContext(
            <CreateTransferForm isOpen onClose={noop} onSuccess={noop} />,
            { identity }
        );

        await openAndSelect('Select Account', 'From Co');
        await openAndSelect('Select Subaccount', 'Sub A');
        await typeAndSelectProject('Proj', 'Proj');
        await openAndSelect('Select Account', 'To Co');

        // The product/track tree is empty, but a label-mode transfer only needs
        // the project id, so Next must be enabled.
        await waitFor(() =>
            expect(screen.getByRole('button', { name: 'Next' })).toBeEnabled()
        );
    });

    it('proceeds to the terms step and submits a label transfer by project id with an empty tree', async () => {
        renderInAppContext(
            <CreateTransferForm isOpen onClose={noop} onSuccess={noop} />,
            { identity }
        );

        await openAndSelect('Select Account', 'From Co');
        await openAndSelect('Select Subaccount', 'Sub A');
        await typeAndSelectProject('Proj', 'Proj');
        await openAndSelect('Select Account', 'To Co');

        fireEvent.click(await screen.findByRole('button', { name: 'Next' }));

        // The terms step renders even though the product tree is empty (label
        // mode is the default and needs no products/tracks).
        expect(await screen.findByText('Set up Terms')).toBeInTheDocument();

        fireEvent.click(
            screen.getByRole('button', { name: 'Submit Transfer' })
        );

        await waitFor(() => expect(mockCreate).toHaveBeenCalledTimes(1));
        expect(mockCreate.mock.calls[0][0]).toMatchObject({ projectId: '42' });
    });
});
