import React, { forwardRef } from 'react';
import { render, waitFor } from '@testing-library/react';

import { PluginRender } from './Plugin';
import { ResourceBrowserPluginType } from '../types';
import * as RBI from '../ResourceBrowserInput/ResourceBrowserInput';
import * as RBInlineButton from '../ResourceBrowserInlineButton/ResourceBrowserInlineButton';
import * as AuthContext from '../ResourceBrowserContext/AuthProvider';

jest.spyOn(RBI, 'ResourceBrowserInput');
jest.mock('../ResourceBrowserInlineButton/ResourceBrowserInlineButton', () => ({
    ResourceBrowserInlineButton: jest.fn(() => <div data-testid="mocked-inline-button" />),
}));
jest.spyOn(AuthContext, 'AuthProvider');

const baseProps = {
    type: null,
    modalTitle: 'Asset picker',
    value: null,
    isOtherSourceValue: false,
    onChange: jest.fn(),
    onClear: jest.fn(),
    useResource: () => ({ data: null, error: null, isLoading: false }),
    plugin: null,
    pluginMode: null,
    searchEnabled: false,
    source: null,
    sources: [],
    isLoading: false,
    error: null,
    setSource: jest.fn(),
    isModalOpen: false,
    onModalStateChange: jest.fn(),
    onRetry: jest.fn(),
};

describe('Plugin', () => {
    it('Does not render ResourceBrowserInput if render is false', async () => {
        //@ts-ignore
        render(<PluginRender render={false} inline={false} />);

        await waitFor(() => {
            expect(RBI.ResourceBrowserInput).not.toHaveBeenCalled();
        });
    });

    it('Does render ResourceBrowserInput if render is true', async () => {
        const props = baseProps;
        render(<PluginRender render={true} inline={false} {...props} />);

        await waitFor(() => {
            expect(RBI.ResourceBrowserInput).toHaveBeenCalledWith(props, {});
        });
    });

    it('Does render ResourceBrowserInlineButton if inline is true', async () => {
        const props = baseProps;
        render(<PluginRender render={true} inline={true} inlineType="image" {...props} />);

        await waitFor(() => {
            expect(RBInlineButton.ResourceBrowserInlineButton).toHaveBeenCalledWith({ ...props, inlineType: 'image' }, {});
        });
    });

    it('Wraps content in AuthProvider when source requires auth', async () => {
        const sourceWithAuth = {
            id: '123',
            type: 'dam' as ResourceBrowserPluginType,
            configuration: {
                authUrl: 'https://example.com/auth',
                redirectUrl: 'https://example.com/redirect',
                clientId: 'abc123',
                scope: 'scope1',
            },
        };

        const props = { ...baseProps, source: sourceWithAuth };
        render(<PluginRender render={true} inline={false} {...props} />);

        await waitFor(() => {
            expect(AuthContext.AuthProvider).toHaveBeenCalledWith({ authConfig: sourceWithAuth, children: expect.anything() }, {});
        });
    });

    it('Wraps content in AuthProvider when alwaysUseResourceRequestProxy is true', async () => {
        const sourceWithAuth = {
            id: '123',
            type: 'dam' as ResourceBrowserPluginType,
            configuration: {
                alwaysUseResourceRequestProxy: true,
            },
        };

        const props = { ...baseProps, source: sourceWithAuth };
        render(<PluginRender render={true} inline={false} {...props} />);

        await waitFor(() => {
            expect(AuthContext.AuthProvider).toHaveBeenCalledWith({ authConfig: sourceWithAuth, children: expect.anything() }, {});
        });
    });
});
