import React from 'react';
import { ApolloError } from '@apollo/client';
import { renderInAppContext } from '@theorchard/suite-testing';
import dayjs from 'dayjs';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import utc from 'dayjs/plugin/utc';
import { ProfileType } from 'src/data/globalTypes';
import * as audioAttrQuery from 'src/data/queries/audioAttributes/audioAttributes';
import * as osrQuery from 'src/data/queries/orchardSoundRecordings/orchardSoundRecordings';
import * as rightsAttrQuery from 'src/data/queries/rightsAttributes/rightsAttributes';
import * as territoriesQuery from 'src/data/queries/territories/territories';
import { TrackMetadata } from 'src/data/queries/track/selector';
import * as trackQuery from 'src/data/queries/track/track';
import TrackPage, { CLASS_NAME } from '../trackPage';

dayjs.extend(utc);

const data: TrackMetadata = {
    track: {
        tuid: '123',
        isrc: 'ISRC1',
        name: 'track name',
        pInfo: '2025 Label',
        originalRightsHolderCountry: 'FR',
        recordingCountry: 'FR',
        ownershipRights: null,
        fingerprintRights: 'Non Exclusive, Eligible Offer Type',
        accountId: 123,
        accountType: 'Vendor',
        accountName: 'Vendor Name',
        productDistribution: 'Digital',
        primaryArtists: ['artist name'],
        featuringArtists: [],
        audioAttributes: [],
        rightsAttributes: [],
        rules: [
            {
                active: true,
                policy: 'Monetize',
                service: 'Meta',
                territory: 'FR',
                startDate: dayjs
                    .utc('2023-01-02T00:00:00.000Z')
                    .format('D MMM YYYY HH:mm:ss'),
                endDate: '-',
                createdDate: dayjs
                    .utc('2023-01-01T00:00:00.000Z')
                    .format('D MMM YYYY HH:mm:ss'),
                lastModifiedDate: dayjs
                    .utc('2023-01-01T00:00:00.000Z')
                    .format('D MMM YYYY HH:mm:ss'),
                createdBy: {
                    profileId: '123',
                    profileType: 'CONTENT' as ProfileType,
                    profileName: 'Name',
                },
                lastModifiedBy: {
                    profileId: '123',
                    profileType: 'CONTENT' as ProfileType,
                    profileName: 'Name',
                },
            },
        ],
        vendorRules: [
            {
                active: true,
                policy: 'Monetize',
                service: 'Meta',
                territory: '*',
                startDate: dayjs
                    .utc('2023-01-02T00:00:00.000Z')
                    .format('D MMM YYYY HH:mm:ss'),
                endDate: '-',
                createdDate: dayjs
                    .utc('2023-01-01T00:00:00.000Z')
                    .format('D MMM YYYY HH:mm:ss'),
                lastModifiedDate: dayjs
                    .utc('2023-01-01T00:00:00.000Z')
                    .format('D MMM YYYY HH:mm:ss'),
                createdBy: {
                    profileId: '123',
                    profileType: 'CONTENT' as ProfileType,
                    profileName: 'Name',
                },
                lastModifiedBy: {
                    profileId: '123',
                    profileType: 'CONTENT' as ProfileType,
                    profileName: 'Name',
                },
            },
        ],
        subaccountRules: [],
    },
};

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

    test('render loading element while waiting for track query', () => {
        jest.spyOn(trackQuery, 'useTrackQuery').mockReturnValue({
            loading: true,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(territoriesQuery, 'useTerritoriesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { territories: [] },
        });
        jest.spyOn(audioAttrQuery, 'useAudioAttributesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { audioAttributes: [] },
        });
        jest.spyOn(rightsAttrQuery, 'useRightsAttributesQuery').mockReturnValue(
            {
                loading: false,
                error: undefined,
                data: [],
            }
        );
        jest.spyOn(osrQuery, 'useOrchardSoundRecordingsQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { orchardSoundRecordings: { orchardSoundRecordings: [] } },
        });

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

        expect(trackQuery.useTrackQuery).toHaveBeenCalled();
        expect(territoriesQuery.useTerritoriesQuery).toHaveBeenCalled();
        expect(audioAttrQuery.useAudioAttributesQuery).toHaveBeenCalled();
        expect(rightsAttrQuery.useRightsAttributesQuery).toHaveBeenCalled();
        expect(osrQuery.useOrchardSoundRecordingsQuery).toHaveBeenCalled();
        expect(loadingClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render loading element while waiting for territories query', () => {
        jest.spyOn(territoriesQuery, 'useTerritoriesQuery').mockReturnValue({
            loading: true,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(trackQuery, 'useTrackQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data,
        });
        jest.spyOn(audioAttrQuery, 'useAudioAttributesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { audioAttributes: [] },
        });
        jest.spyOn(rightsAttrQuery, 'useRightsAttributesQuery').mockReturnValue(
            {
                loading: false,
                error: undefined,
                data: [],
            }
        );
        jest.spyOn(osrQuery, 'useOrchardSoundRecordingsQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { orchardSoundRecordings: { orchardSoundRecordings: [] } },
        });

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

        expect(trackQuery.useTrackQuery).toHaveBeenCalled();
        expect(territoriesQuery.useTerritoriesQuery).toHaveBeenCalled();
        expect(loadingClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render alert element when error for track query', () => {
        jest.spyOn(trackQuery, 'useTrackQuery').mockReturnValue({
            loading: false,
            error: new ApolloError({ errorMessage: 'Error' }),
            data: undefined,
        });
        jest.spyOn(territoriesQuery, 'useTerritoriesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { territories: [] },
        });
        jest.spyOn(audioAttrQuery, 'useAudioAttributesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { audioAttributes: [] },
        });
        jest.spyOn(rightsAttrQuery, 'useRightsAttributesQuery').mockReturnValue(
            {
                loading: false,
                error: undefined,
                data: [],
            }
        );
        jest.spyOn(osrQuery, 'useOrchardSoundRecordingsQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { orchardSoundRecordings: { orchardSoundRecordings: [] } },
        });

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

        expect(trackQuery.useTrackQuery).toHaveBeenCalled();
        expect(territoriesQuery.useTerritoriesQuery).toHaveBeenCalled();
        expect(alertClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render alert element when error for territories query', () => {
        jest.spyOn(trackQuery, 'useTrackQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data,
        });
        jest.spyOn(territoriesQuery, 'useTerritoriesQuery').mockReturnValue({
            loading: false,
            error: new ApolloError({ errorMessage: 'Error' }),
            data: undefined,
        });
        jest.spyOn(audioAttrQuery, 'useAudioAttributesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { audioAttributes: [] },
        });
        jest.spyOn(rightsAttrQuery, 'useRightsAttributesQuery').mockReturnValue(
            {
                loading: false,
                error: undefined,
                data: [],
            }
        );
        jest.spyOn(osrQuery, 'useOrchardSoundRecordingsQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { orchardSoundRecordings: { orchardSoundRecordings: [] } },
        });

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

        expect(trackQuery.useTrackQuery).toHaveBeenCalled();
        expect(territoriesQuery.useTerritoriesQuery).toHaveBeenCalled();
        expect(alertClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render info when no track found', () => {
        jest.spyOn(trackQuery, 'useTrackQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(territoriesQuery, 'useTerritoriesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { territories: [] },
        });
        jest.spyOn(audioAttrQuery, 'useAudioAttributesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { audioAttributes: [] },
        });
        jest.spyOn(rightsAttrQuery, 'useRightsAttributesQuery').mockReturnValue(
            {
                loading: false,
                error: undefined,
                data: [],
            }
        );
        jest.spyOn(osrQuery, 'useOrchardSoundRecordingsQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { orchardSoundRecordings: { orchardSoundRecordings: [] } },
        });

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

        expect(trackQuery.useTrackQuery).toHaveBeenCalled();
        expect(territoriesQuery.useTerritoriesQuery).toHaveBeenCalled();
        expect(infoMessageClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render info when no territories found', () => {
        jest.spyOn(trackQuery, 'useTrackQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data,
        });
        jest.spyOn(territoriesQuery, 'useTerritoriesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: undefined,
        });
        jest.spyOn(audioAttrQuery, 'useAudioAttributesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { audioAttributes: [] },
        });
        jest.spyOn(rightsAttrQuery, 'useRightsAttributesQuery').mockReturnValue(
            {
                loading: false,
                error: undefined,
                data: [],
            }
        );
        jest.spyOn(osrQuery, 'useOrchardSoundRecordingsQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { orchardSoundRecordings: { orchardSoundRecordings: [] } },
        });

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

        expect(trackQuery.useTrackQuery).toHaveBeenCalled();
        expect(territoriesQuery.useTerritoriesQuery).toHaveBeenCalled();
        expect(infoMessageClassname).toBeVisible();

        jest.restoreAllMocks();
    });

    test('render track page', () => {
        jest.spyOn(trackQuery, 'useTrackQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data,
        });
        jest.spyOn(territoriesQuery, 'useTerritoriesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { territories: [] },
        });

        jest.spyOn(audioAttrQuery, 'useAudioAttributesQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { audioAttributes: [] },
        });
        jest.spyOn(rightsAttrQuery, 'useRightsAttributesQuery').mockReturnValue(
            {
                loading: false,
                error: undefined,
                data: [],
            }
        );
        jest.spyOn(osrQuery, 'useOrchardSoundRecordingsQuery').mockReturnValue({
            loading: false,
            error: undefined,
            data: { orchardSoundRecordings: { orchardSoundRecordings: [] } },
        });

        const { container, getByTestId } = renderPage();
        const pageHeaderClassname = getByTestId('PageHeader');
        const pageHeaderPrimaryClassname = getByTestId('PageHeaderPrimary');
        const pageHeaderSecondaryClassname = getByTestId('PageHeaderSecondary');
        const pagebodyClassname = container.querySelector('.PageBody');
        const pageNavClassname = container.querySelector('.PageNav');
        const rightsViewClassname = container.querySelector(
            `.${CLASS_NAME}-Views-RightsView`
        );
        const trackTitleClassname = container.querySelector(
            `.${CLASS_NAME}-header-track-name`
        );

        expect(trackQuery.useTrackQuery).toHaveBeenCalled();
        expect(territoriesQuery.useTerritoriesQuery).toHaveBeenCalled();
        expect(audioAttrQuery.useAudioAttributesQuery).toHaveBeenCalled();
        expect(rightsAttrQuery.useRightsAttributesQuery).toHaveBeenCalled();
        expect(osrQuery.useOrchardSoundRecordingsQuery).toHaveBeenCalled();

        expect(pageHeaderClassname).toBeVisible();
        expect(pageHeaderPrimaryClassname).toBeVisible();
        expect(pageHeaderSecondaryClassname).toBeVisible();
        expect(pagebodyClassname).toBeVisible();
        expect(pageNavClassname).toBeVisible();
        expect(rightsViewClassname).toBeVisible();
        expect(trackTitleClassname?.innerHTML).toBe('<h2>track name</h2>');

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