import React, { useState } from 'react';
import { fireEvent, screen } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import { ABACUS_PROFILE } from 'src/constants';
import DetailsStep from '../create-transfer/details-step';
import type { TwoLineOption } from '../types';
import type { AccountForTransfer } from 'src/apollo/queries/account';

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

const MOCK_ACCOUNT = {
    accountId: 'acc-1',
    accountName: 'Acme Records',
    vendor: { vendorId: 101 },
} as AccountForTransfer;

const PROJECT_OPTIONS: TwoLineOption[] = [
    { label: 'My Project', value: '42', subtitle: '42 · CODE · 1 Product' },
];

const FROM_SUBACCOUNT_OPTIONS: TwoLineOption[] = [
    { label: 'Sub A', value: '88046', subtitle: '88046' },
];

// Stateful harness so a "Clear account" click flips fromAccount to undefined,
// reproducing the in-app flow of deleting the selected From Account.
const Harness: React.FC = () => {
    const [fromAccount, setFromAccount] = useState<
        AccountForTransfer | undefined
    >(MOCK_ACCOUNT);
    return (
        <>
            <button onClick={() => setFromAccount(undefined)}>
                Clear account
            </button>
            <DetailsStep
                fromAccount={fromAccount}
                toAccount={undefined}
                projectId={undefined}
                contractId={undefined}
                toSubaccountId={undefined}
                toSubaccountOptions={[]}
                fromSubaccountId="88046"
                fromSubaccountOptions={FROM_SUBACCOUNT_OPTIONS}
                contractOptions={[]}
                onLoadFromOptions={async () => ({ data: [], totalCount: 0 })}
                onLoadToOptions={async () => ({ data: [], totalCount: 0 })}
                onLoadProjectOptions={async () => ({
                    data: PROJECT_OPTIONS,
                    totalCount: PROJECT_OPTIONS.length,
                })}
                onFromAccountChange={noop}
                onFromSubaccountChange={noop}
                onToAccountChange={noop}
                onProjectChange={noop}
                onContractChange={noop}
                onToSubaccountChange={noop}
            />
        </>
    );
};

const SINGLE_CONTRACT: TwoLineOption[] = [
    { label: 'Sole Contract', value: 'c-1', subtitle: 'Distribution' },
];

const renderWithContracts = (contractOptions: TwoLineOption[]) =>
    renderInAppContext(
        <DetailsStep
            fromAccount={MOCK_ACCOUNT}
            toAccount={
                {
                    accountId: 'acc-2',
                    accountName: 'Dest Records',
                    vendor: { vendorId: 202 },
                } as AccountForTransfer
            }
            projectId="42"
            contractId={undefined}
            toSubaccountId={undefined}
            toSubaccountOptions={[]}
            fromSubaccountId="88046"
            fromSubaccountOptions={FROM_SUBACCOUNT_OPTIONS}
            contractOptions={contractOptions}
            onLoadFromOptions={async () => ({ data: [], totalCount: 0 })}
            onLoadToOptions={async () => ({ data: [], totalCount: 0 })}
            onLoadProjectOptions={async () => ({
                data: PROJECT_OPTIONS,
                totalCount: PROJECT_OPTIONS.length,
            })}
            onFromAccountChange={noop}
            onFromSubaccountChange={noop}
            onToAccountChange={noop}
            onProjectChange={noop}
            onContractChange={noop}
            onToSubaccountChange={noop}
        />,
        { identity }
    );

const renderOriginStep = (fromSubaccountOptions: TwoLineOption[]) =>
    renderInAppContext(
        <DetailsStep
            fromAccount={MOCK_ACCOUNT}
            toAccount={undefined}
            projectId={undefined}
            contractId={undefined}
            toSubaccountId={undefined}
            toSubaccountOptions={[]}
            fromSubaccountId={undefined}
            fromSubaccountOptions={fromSubaccountOptions}
            contractOptions={[]}
            onLoadFromOptions={async () => ({ data: [], totalCount: 0 })}
            onLoadToOptions={async () => ({ data: [], totalCount: 0 })}
            onLoadProjectOptions={async () => ({
                data: PROJECT_OPTIONS,
                totalCount: PROJECT_OPTIONS.length,
            })}
            onFromAccountChange={noop}
            onFromSubaccountChange={noop}
            onToAccountChange={noop}
            onProjectChange={noop}
            onContractChange={noop}
            onToSubaccountChange={noop}
        />,
        { identity }
    );

describe('DetailsStep — origin subaccount', () => {
    it('hides the selector and opens the project picker when the account has no subaccounts', async () => {
        renderOriginStep([]);

        expect(screen.queryByText('From Subaccount')).not.toBeInTheDocument();
        // The project picker is enabled: it opens to its type-to-search box.
        fireEvent.click(screen.getByText('Select Project'));
        expect(
            await screen.findByPlaceholderText('Search project')
        ).toBeInTheDocument();
    });

    it('shows a required selector and keeps the project picker closed until one is picked', () => {
        renderOriginStep(FROM_SUBACCOUNT_OPTIONS);

        expect(screen.getByText('From Subaccount')).toBeInTheDocument();
        // No subaccount chosen yet, so the project picker is disabled and does
        // not open its search box.
        fireEvent.click(screen.getByText('Select Project'));
        expect(
            screen.queryByPlaceholderText('Search project')
        ).not.toBeInTheDocument();
    });
});

describe('DetailsStep — single contract tooltip', () => {
    it('explains the auto-selection on hover when only one contract exists', async () => {
        renderWithContracts(SINGLE_CONTRACT);

        const trigger = document.querySelector('#single-contract-tooltip');
        expect(trigger).not.toBeNull();
        fireEvent.mouseOver(trigger as Element);

        expect(
            await screen.findByText(/only one contract/i)
        ).toBeInTheDocument();
    });

    it('shows no single-contract tooltip when several contracts exist', () => {
        renderWithContracts([
            ...SINGLE_CONTRACT,
            { label: 'Second Contract', value: 'c-2', subtitle: 'Publishing' },
        ]);

        expect(document.querySelector('#single-contract-tooltip')).toBeNull();
    });
});

describe('DetailsStep', () => {
    it('closes the open Project dropdown when the From Account is cleared', async () => {
        renderInAppContext(<Harness />, { identity });

        // Open the Project dropdown.
        fireEvent.click(screen.getByText('Select Project'));
        expect(
            await screen.findByPlaceholderText('Search project')
        ).toBeInTheDocument();

        // Clearing the account disables the Project select; its open menu must
        // not linger floating over the page.
        fireEvent.click(screen.getByText('Clear account'));

        expect(
            screen.queryByPlaceholderText('Search project')
        ).not.toBeInTheDocument();
    });
});
