import React from 'react';
import { render } from '@testing-library/react';
import { AppConfigContext, SuiteAppConfig } from '@theorchard/suite-config';
import { ErrorBoundary } from 'lib/test-utils/error';
import { get } from 'lodash-es';
import { CdnAsset, CdnAssetProps, Manifest, VariantType, CDN_MANIFEST } from '../cdnAsset';

describe('<CdnAsset>', () => {
    function renderComponent<
        C extends keyof Manifest,
        N extends keyof Manifest[C],
        S extends keyof Manifest[C][N],
        V extends VariantType<Manifest[C][N][S]>,
    >(props: CdnAssetProps<C, N, S, V>, brand?: string) {
        return render(<CdnAsset {...props} />, {
            wrapper: ({ children }) => (
                <ErrorBoundary>
                    <AppConfigContext.Provider
                        value={{
                            config: {
                                cdnUrl: 'https//cdn.test.com/',
                                brand,
                            } as SuiteAppConfig,
                        }}
                    >
                        {children}
                    </AppConfigContext.Provider>
                </ErrorBoundary>
            ),
        });
    }

    beforeEach(() => {
        jest.spyOn(console, 'error').mockImplementation();
    });

    test('manifest matches snapshot', () => {
        expect(CDN_MANIFEST).toMatchSnapshot();
    });

    test('accepts "title"', () => {
        const title = 'BeatPort';

        const { getByTestId } = renderComponent({
            category: 'stores',
            name: 'beatport',
            title,
        });

        const imgElement = getByTestId('CdnIcon');

        expect(imgElement).toHaveAttribute('title', title);
    });

    describe('brands', () => {
        test('renders', () => {
            const { getByTestId } = renderComponent({
                category: 'brands',
                name: 'awal',
                size: '16',
            });

            const fileName = get(CDN_MANIFEST, 'brands.awal.16.color');

            const imgElement = getByTestId('CdnIcon');

            expect(imgElement).toHaveAttribute(
                'src',
                `https//cdn.test.com/assets/brands/${fileName}`
            );
        });

        test('renders default size as 16px', () => {
            const { getByTestId } = renderComponent({
                category: 'brands',
                name: 'awal',
            });

            const fileName = get(CDN_MANIFEST, 'brands.awal.16.color');

            const imgElement = getByTestId('CdnIcon');

            expect(imgElement).toHaveAttribute(
                'src',
                `https//cdn.test.com/assets/brands/${fileName}`
            );
        });

        test('accepts custom dimensions', () => {
            const { getByTestId } = renderComponent({
                category: 'brands',
                name: 'sme',
                width: '24',
                height: '20',
            });

            const fileName = get(CDN_MANIFEST, 'brands.sme.16.color');
            const imgElement = getByTestId('CdnIcon');

            expect(imgElement).toHaveAttribute('width', '24');
            expect(imgElement).toHaveAttribute('height', '20');
            expect(imgElement).toHaveAttribute(
                'src',
                `https//cdn.test.com/assets/brands/${fileName}`
            );
        });
    });

    describe('with unknown category', () => {
        test('throws error', () => {
            const { getByTestId } = renderComponent({
                category: 'nothing' as never,
                name: 'error',
            });

            const error = getByTestId('Error');

            expect(error).toHaveTextContent(
                'Unknown CDN asset category "nothing". Available values are: ["countries","logos","brands","stores"]'
            );
        });
    });

    describe('with unknown name', () => {
        test('throws error', () => {
            const { getByTestId } = renderComponent({
                category: 'brands',
                name: 'nothing' as never,
            });

            const error = getByTestId('Error');

            expect(error).toHaveTextContent(
                'Unknown CDN asset name "brands/[nothing]". Available values are: ["ab","altafonte","awal","drm","foundation","knr","ma","msk","orchard","sme"]'
            );
        });
    });

    describe('with unknown size', () => {
        test('throws error', () => {
            const { getByTestId } = renderComponent({
                category: 'brands',
                name: 'awal',
                size: '1000px' as never,
            });

            const error = getByTestId('Error');

            expect(error).toHaveTextContent(
                'Unknown CDN asset size "brands/awal/[1000px]". Available values are: ["16","24","48","full"]'
            );
        });
    });

    describe('with unknown variant', () => {
        test('throws error', () => {
            const { getByTestId } = renderComponent({
                category: 'brands',
                name: 'msk',
                size: '48',
                variant: 'apple' as never,
            });

            const error = getByTestId('Error');

            expect(error).toHaveTextContent(
                'Unknown CDN asset variant "brands/msk/48/[apple]". Available values are: ["color","dark","light"]'
            );
        });
    });
});
