import { render } from '@testing-library/react';
import { notFound } from 'next/navigation';
import { getSettings } from '@/actions/getSettings';
import { getSubscriptions } from '@/actions/getSubscriptions';
import SubscriptionsPage from './page';
import { SubscriptionsScreen } from './SubscriptionsScreen';
import type { Mock } from 'vitest';

vi.mock('next/navigation', () => ({
    notFound: vi.fn(),
}));

vi.mock('@/actions/getSubscriptions', () => ({
    getSubscriptions: vi.fn().mockReturnValue({}),
}));

vi.mock('@/actions/getSettings', () => ({
    getSettings: vi.fn().mockReturnValue({}),
}));

vi.mock('./SubscriptionsScreen', () => ({
    SubscriptionsScreen: vi.fn(() => <div>SubscriptionsScreen</div>),
}));

describe('<SettingsPage>', () => {
    afterEach(() => {
        vi.clearAllMocks();
    });

    describe('when resolved with "data"', () => {
        it('should render "SubscriptionsScreen" with correct props', async () => {
            const getSubscriptionsResolvedValue = {
                data: [
                    {
                        id: 'subscription-id',
                        name: 'Subscription name',
                        isActive: true,
                    },
                ],
            };
            (getSubscriptions as Mock).mockResolvedValue(
                getSubscriptionsResolvedValue
            );

            const props = {
                params: Promise.resolve({ locale: 'en', token: 'token' }),
                searchParams: Promise.resolve({}),
            };

            render(await SubscriptionsPage(props));

            expect(SubscriptionsScreen).toHaveBeenCalledWith(
                {
                    items: getSubscriptionsResolvedValue.data,
                },
                undefined
            );
        });
    });

    describe('when "getSubscriptions" returns an error', () => {
        describe('when error type is "PAGE_NOT_FOUND"', () => {
            it('should call "notFound" page', async () => {
                (getSubscriptions as Mock).mockResolvedValue({
                    error: { type: 'PAGE_NOT_FOUND' },
                });
                (getSettings as Mock).mockResolvedValue({ data: {} });

                const props = {
                    params: Promise.resolve({ locale: 'en', token: 'token' }),
                    searchParams: Promise.resolve({}),
                };

                render(await SubscriptionsPage(props));

                expect(notFound).toBeCalled();
            });
        });

        describe('when error type is any other', () => {
            it('should throw that error', async () => {
                const error = { type: 'BAD_REQUEST', message: 'Bad request' };

                (getSubscriptions as Mock).mockResolvedValue({ error });
                (getSettings as Mock).mockResolvedValue({ data: {} });

                const props = {
                    params: Promise.resolve({ locale: 'en', token: 'token' }),
                    searchParams: Promise.resolve({}),
                };

                expect(await SubscriptionsPage(props).catch(err => err)).toBe(
                    error.message
                );
            });
        });
    });
});
