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

import { ResourceBrowserPlugin } from '../types';
import { mockResource } from '../__mocks__/MockModels';

const defaultProps: any = {
    resource: null,
    allowedTypes: undefined,
    isLoading: false,
    isError: false,
    isOtherSourceValue: false,
};

describe('Resource picker', () => {
    it('should render the initial state with the default label', () => {
        render(<ResourcePicker {...defaultProps} />);
        const pickerLabel = screen.getByText('Choose asset');

        expect(pickerLabel).toBeInTheDocument();
    });

    it("should render the initial state with the image label if it's an image picker", () => {
        render(<ResourcePicker {...defaultProps} allowedTypes={['image']} />);
        const pickerLabel = screen.getByText('Choose image');

        expect(pickerLabel).toBeInTheDocument();
    });

    it('should render the loading state if set to true', () => {
        render(<ResourcePicker {...defaultProps} isLoading={true} />);
        const pickerLabel = screen.queryByText('Choose image');
        const loadingLabel = screen.queryByLabelText('Loading selection');

        expect(pickerLabel).not.toBeInTheDocument();
        expect(loadingLabel).toBeInTheDocument();
    });

    it('should render the loading state if isOtherSourceValue is set to true', () => {
        render(<ResourcePicker {...defaultProps} isLoading={false} isOtherSourceValue={true} />);
        const pickerLabel = screen.queryByText('Choose image');
        const loadingLabel = screen.queryByLabelText('Loading selection');

        expect(pickerLabel).not.toBeInTheDocument();
        expect(loadingLabel).toBeInTheDocument();
    });

    it('should render the error state if set to true', () => {
        const errorMessage = 'Failed to retrieve asset info due to a Component Service API key problem.';

        render(<ResourcePicker {...defaultProps} error={new Error(errorMessage)} />);
        const pickerLabel = screen.queryByText('Choose image');
        const errorLabel = screen.queryByText(errorMessage);

        expect(pickerLabel).not.toBeInTheDocument();
        expect(errorLabel).toBeInTheDocument();
    });

    it('should render the selected state if there is a resource returned (icon)', async () => {
        const resource = mockResource();
        const plugin: Partial<ResourceBrowserPlugin> = {
            type: 'dam',
            renderSelectedResource: jest.fn().mockResolvedValue({
                showThumbnail: false,
                icon: <div>IconGoesHere</div>,
                label: 'Products',
                description: [<div key="1">DescriptionFirstLine</div>, <div key="2">DescriptionSecondLine</div>],
            }),
        };

        render(<ResourcePicker {...defaultProps} plugin={plugin as ResourceBrowserPlugin} resource={resource} />);
        const pickerLabel = screen.queryByText('Choose image');

        expect(pickerLabel).not.toBeInTheDocument();

        // Includes the plugin response in the document
        await waitFor(() => {
            expect(screen.queryByText('Products')).toBeInTheDocument();
            expect(screen.queryByText('IconGoesHere')).toBeInTheDocument();
            expect(screen.queryByText('DescriptionFirstLine')).toBeInTheDocument();
            expect(screen.queryByText('DescriptionSecondLine')).toBeInTheDocument();
        });
    });

    it('should render the selected state if there is a resource returned (thumbnail)', async () => {
        const resource = mockResource();
        const plugin: Partial<ResourceBrowserPlugin> = {
            type: 'dam',
            renderSelectedResource: jest.fn().mockResolvedValue({
                showThumbnail: true,
                icon: <div>IconGoesHere</div>,
                label: 'Products',
                description: [<div key="1">DescriptionFirstLine</div>, <div key="2">DescriptionSecondLine</div>],
            }),
        };

        render(<ResourcePicker {...defaultProps} plugin={plugin as ResourceBrowserPlugin} resource={resource} />);
        const pickerLabel = screen.queryByText('Choose image');

        expect(pickerLabel).not.toBeInTheDocument();

        // Includes the plugin response in the document
        await waitFor(() => {
            expect(screen.queryByText('Products')).toBeInTheDocument();
            expect(screen.queryByAltText('an-image-name')).toBeInTheDocument();
            expect(screen.queryByText('DescriptionFirstLine')).toBeInTheDocument();
            expect(screen.queryByText('DescriptionSecondLine')).toBeInTheDocument();
        });
    });

    it('should display the reset button in selected state', async () => {
        const resource = mockResource();
        const plugin: Partial<ResourceBrowserPlugin> = {
            type: 'dam',
            renderSelectedResource: jest.fn().mockResolvedValue({
                icon: <></>,
                label: 'Products',
                description: [],
            }),
        };

        render(<ResourcePicker {...defaultProps} plugin={plugin as ResourceBrowserPlugin} resource={resource} />);

        await waitFor(() => {
            const resourceName = screen.queryByText('Products');
            const removeButton = screen.queryByLabelText('Remove selection');

            expect(resourceName).toBeInTheDocument();
            expect(removeButton).toBeInTheDocument();
        });
    });

    it('should display disabled reset button in selected + disabled state', async () => {
        const plugin: Partial<ResourceBrowserPlugin> = {
            type: 'dam',
            renderSelectedResource: jest.fn().mockResolvedValue({
                icon: <></>,
                label: 'Products',
                description: [],
            }),
        };
        const resource = mockResource();
        render(<ResourcePicker {...defaultProps} isDisabled={true} plugin={plugin as ResourceBrowserPlugin} resource={resource} />);

        await waitFor(() => {
            expect(screen.queryByLabelText('Remove selection')).toBeDisabled();
        });
    });

    it('should display the reset button in error state', () => {
        const errorMessage = 'Failed to fetch resource.';

        render(<ResourcePicker {...defaultProps} error={new Error(errorMessage)} />);
        const errorLabel = screen.queryByText(errorMessage);
        const removeButton = screen.queryByLabelText('Remove selection');

        expect(errorLabel).toBeInTheDocument();
        expect(removeButton).toBeInTheDocument();
    });

    it('should display disabled reset button in error + disabled state', () => {
        render(<ResourcePicker {...defaultProps} isDisabled={true} error={new Error('Failed to fetch resource.')} />);

        expect(screen.queryByLabelText('Remove selection')).toBeDisabled();
    });

    it('should not display the reset button in the empty state', () => {
        render(<ResourcePicker {...defaultProps} />);
        const pickerLabel = screen.getByText('Choose asset');
        const removeButton = screen.queryByLabelText('Remove selection');

        expect(pickerLabel).toBeInTheDocument();
        expect(removeButton).not.toBeInTheDocument();
    });
});
