import React from 'react';
import { ApolloError } from '@apollo/client';
import { Segment } from '@theorchard/suite-frontend';
import { renderInAppContext } from '@theorchard/suite-testing';
import * as osr from 'src/data/queries/orchardSoundRecording/orchardSoundRecording';
import { OrchardSoundRecordingMetadata } from 'src/data/queries/orchardSoundRecording/selector';
import * as trackAttributes from 'src/data/queries/orchardSoundRecording/trackAttributes';
import OsrPage, { CLASS_NAME } from '../osrPage';

const data: OrchardSoundRecordingMetadata = {
    id: 'uuid',
    isrc: 'isrc',
    isActive: true,
    creationDate: '2022-10-19T13:41:17.000Z',
    primaryTrack: {
        position: 1,
        name: 'name',
        isrc: 'isrc',
        trackId: 123,
        duration: '3:0',
        genre: 'genre',
        accountName: 'account',
        accountId: 456,
        upc: 'upc',
        productId: 789,
        productStatus: 'status',
        releaseDate: '2022-01-01',
        countriesClaimed: ['FR'],
        pLine: 'pline',
        primaryArtists: ['artist1'],
        featuringArtists: ['artist2'],
        producerArtists: ['artist3'],
        language: 'FR',
        metaLanguageCode: 'FR',
        originalRightsHolderCountry: 'FR',
        recordingCountry: 'FR',
        soundRecordingParticipations: [
            {
                participant: {
                    name: 'artist',
                    uuid: 'uuid2',
                },
                role: {
                    name: 'role',
                    category: {
                        name: 'category',
                    },
                },
            },
        ],
        ownershipRights: 'Non Exclusive, Ineligible Offer Type',
        audioAttributes: ['N/A'],
        rightsAttributes: ['Public Domain'],
        rules: [],
        product: {
            label: {
                rules: [],
                vendor: { rules: [] },
                type: 'account',
                id: {
                    vendor: 456,
                    subaccount: undefined,
                },
            },
        },
        isActive: true,
    },
    tracks: [
        {
            position: 1,
            name: 'name',
            isrc: 'isrc',
            trackId: 123,
            duration: '3:0',
            genre: 'genre',
            accountName: 'account',
            accountId: 456,
            upc: 'upc',
            productId: 789,
            productStatus: 'status',
            releaseDate: '2022-01-01',
            countriesClaimed: ['FR'],
            pLine: 'pline',
            primaryArtists: ['artist1'],
            featuringArtists: ['artist2'],
            producerArtists: ['artist3'],
            language: 'FR',
            metaLanguageCode: 'FR',
            originalRightsHolderCountry: 'FR',
            recordingCountry: 'FR',
            soundRecordingParticipations: [
                {
                    participant: {
                        name: 'artist',
                        uuid: 'uuid2',
                    },
                    role: {
                        name: 'role',
                        category: {
                            name: 'category',
                        },
                    },
                },
            ],
            ownershipRights: 'Non Exclusive, Ineligible Offer Type',
            audioAttributes: ['N/A'],
            rightsAttributes: ['Public Domain'],
            rules: [],
            product: {
                label: {
                    type: 'account',
                    id: {
                        vendor: 1,
                        subaccount: undefined,
                    },
                    rules: [],
                    vendor: {
                        rules: [],
                    },
                },
            },
            isActive: true,
        },
    ],
    versionId: 'VERSION_ID',
};

const missingData: OrchardSoundRecordingMetadata = {
    id: 'uuid',
    isrc: 'isrc',
    isActive: false,
    versionId: undefined,
    creationDate: '2022-10-19T13:41:17.000Z',
};

describe('<OsrPage>', () => {
    const renderPage = () => renderInAppContext(<OsrPage />);

    test('render loading element while waiting for osr query', () => {
        jest.spyOn(osr, 'useOsrQuery').mockReturnValue({
            loading: true,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(osr, 'useReferenceTrackImageQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(
            trackAttributes,
            'useGetTrackAttributesQuery'
        ).mockReturnValue({
            loading: false,
            error: undefined,
            data: [],
        });

        const { container } = renderPage();
        const loadingClassname = container.querySelector('.LoadingIndicator');

        expect(osr.useOsrQuery).toHaveBeenCalled();
        expect(osr.useReferenceTrackImageQuery).toHaveBeenCalled();

        expect(loadingClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render loading element while waiting for track image query', () => {
        jest.spyOn(osr, 'useOsrQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(osr, 'useReferenceTrackImageQuery').mockReturnValue({
            loading: true,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(
            trackAttributes,
            'useGetTrackAttributesQuery'
        ).mockReturnValue({
            loading: false,
            error: undefined,
            data: [],
        });

        const { container } = renderPage();
        const loadingClassname = container.querySelector('.LoadingIndicator');

        expect(osr.useOsrQuery).toHaveBeenCalled();
        expect(osr.useReferenceTrackImageQuery).toHaveBeenCalled();

        expect(loadingClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render alert element when error for osr query', () => {
        jest.spyOn(osr, 'useOsrQuery').mockReturnValue({
            loading: false,
            error: new ApolloError({ errorMessage: 'Error' }),
            data: undefined,
        });
        jest.spyOn(osr, 'useReferenceTrackImageQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(
            trackAttributes,
            'useGetTrackAttributesQuery'
        ).mockReturnValue({
            loading: false,
            error: undefined,
            data: [],
        });

        const { container } = renderPage();
        const alertClassname = container.querySelector('.Alert');

        expect(osr.useOsrQuery).toHaveBeenCalled();
        expect(osr.useReferenceTrackImageQuery).toHaveBeenCalled();

        expect(alertClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render alert element when error for track image query', () => {
        jest.spyOn(osr, 'useOsrQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(osr, 'useReferenceTrackImageQuery').mockReturnValue({
            loading: false,
            error: new ApolloError({ errorMessage: 'Error' }),
            data: undefined,
        });
        jest.spyOn(
            trackAttributes,
            'useGetTrackAttributesQuery'
        ).mockReturnValue({
            loading: false,
            error: undefined,
            data: [],
        });

        const { container } = renderPage();
        const alertClassname = container.querySelector('.Alert');

        expect(osr.useOsrQuery).toHaveBeenCalled();
        expect(osr.useReferenceTrackImageQuery).toHaveBeenCalled();

        expect(alertClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render info when no osr found', () => {
        jest.spyOn(osr, 'useOsrQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(osr, 'useReferenceTrackImageQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(
            trackAttributes,
            'useGetTrackAttributesQuery'
        ).mockReturnValue({
            loading: false,
            error: undefined,
            data: [],
        });

        const { container } = renderPage();
        const infoMessageClassname = container.querySelector('.InfoMessage');

        expect(osr.useOsrQuery).toHaveBeenCalled();

        expect(infoMessageClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render no version body when no tracks', () => {
        jest.spyOn(osr, 'useOsrQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: missingData,
        });
        jest.spyOn(osr, 'useReferenceTrackImageQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { referenceTrackImageUrl: 'imageUrl' },
        });
        jest.spyOn(
            trackAttributes,
            'useGetTrackAttributesQuery'
        ).mockReturnValue({
            loading: false,
            error: undefined,
            data: [],
        });
        jest.spyOn(Segment, 'trackEvent');

        const { container } = renderPage();
        const noVersionMainClassname = container.querySelector(
            `.${CLASS_NAME}-no-version`
        );
        const noVersionIconClassname = container.querySelector(
            `.${CLASS_NAME}-no-version-icon`
        );
        const noVersionBodyClassname = container.querySelector(
            `.${CLASS_NAME}-no-version-body`
        );
        const noVersionContactClassname = container.querySelector(
            `.${CLASS_NAME}-no-version-contact`
        );

        expect(osr.useOsrQuery).toHaveBeenCalled();
        expect(Segment.trackEvent).toHaveBeenCalledTimes(1);

        expect(noVersionMainClassname).toBeVisible();
        expect(noVersionIconClassname).toBeVisible();
        expect(noVersionBodyClassname).toBeVisible();
        expect(noVersionContactClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render osr page', () => {
        jest.spyOn(osr, 'useOsrQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data,
        });
        jest.spyOn(osr, 'useReferenceTrackImageQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { referenceTrackImageUrl: 'imageUrl' },
        });
        jest.spyOn(
            trackAttributes,
            'useGetTrackAttributesQuery'
        ).mockReturnValue({
            loading: false,
            error: undefined,
            data: [
                {
                    tuid: '123',
                    audioAttributes: [],
                    rightsAttributes: ['Public Domain'],
                },
            ],
        });

        const { container } = renderPage();
        const pageHeaderClassname = container.querySelector('.SuitePageHeader');
        const pagebodyClassname = container.querySelector('.PageBody');
        const pageNavClassname = container.querySelector('.PageNav');
        const overviewViewClassname = container.querySelector(
            `.${CLASS_NAME}-Views-OverviewView`
        );
        const topLineHeaderClassname = container.querySelector(
            `.${CLASS_NAME}-header-top-line`
        );
        const headerBodyClassname = container.querySelector(
            `.SuitePageHeader-body`
        );
        const headerMainClassname = container.querySelector(
            `.SuitePageHeader-main`
        );
        const inactiveStatusClassname = container.querySelector(
            `.SuitePageHeader-main .SuitePageHeader-title .variant-error`
        );

        expect(osr.useOsrQuery).toHaveBeenCalled();
        expect(osr.useReferenceTrackImageQuery).toHaveBeenCalled();
        expect(trackAttributes.useGetTrackAttributesQuery).toHaveBeenCalled();

        expect(pageHeaderClassname).toBeVisible();
        expect(pagebodyClassname).toBeVisible();
        expect(pageNavClassname).toBeVisible();
        expect(overviewViewClassname).toBeVisible();
        expect(topLineHeaderClassname).toBeVisible();
        expect(headerBodyClassname).toBeVisible();
        expect(headerMainClassname).toBeVisible();
        expect(inactiveStatusClassname).toBeNull();

        jest.restoreAllMocks();
    });

    test('render osr page for inactive track', () => {
        jest.spyOn(osr, 'useOsrQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: {
                ...data,
                isActive: false,
            },
        });
        jest.spyOn(osr, 'useReferenceTrackImageQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { referenceTrackImageUrl: 'imageUrl' },
        });
        jest.spyOn(
            trackAttributes,
            'useGetTrackAttributesQuery'
        ).mockReturnValue({
            loading: false,
            error: undefined,
            data: [
                {
                    tuid: '123',
                    audioAttributes: [],
                    rightsAttributes: ['Public Domain'],
                },
            ],
        });

        const { container } = renderPage();
        const pageHeaderClassname = container.querySelector('.SuitePageHeader');
        const pagebodyClassname = container.querySelector('.PageBody');
        const pageNavClassname = container.querySelector('.PageNav');
        const overviewViewClassname = container.querySelector(
            `.${CLASS_NAME}-Views-OverviewView`
        );
        const topLineHeaderClassname = container.querySelector(
            `.${CLASS_NAME}-header-top-line`
        );
        const headerBodyClassname = container.querySelector(
            `.SuitePageHeader-body`
        );
        const headerMainClassname = container.querySelector(
            `.SuitePageHeader-main`
        );
        const inactiveStatusClassname = container.querySelector(
            `.SuitePageHeader-main .SuitePageHeader-title .variant-error`
        );

        expect(osr.useOsrQuery).toHaveBeenCalled();
        expect(osr.useReferenceTrackImageQuery).toHaveBeenCalled();
        expect(trackAttributes.useGetTrackAttributesQuery).toHaveBeenCalled();

        expect(pageHeaderClassname).toBeVisible();
        expect(pagebodyClassname).toBeVisible();
        expect(pageNavClassname).toBeVisible();
        expect(overviewViewClassname).toBeVisible();
        expect(topLineHeaderClassname).toBeVisible();
        expect(headerBodyClassname).toBeVisible();
        expect(headerMainClassname).toBeVisible();
        expect(inactiveStatusClassname).toBeVisible();

        jest.restoreAllMocks();
    });
});
