import { fireEvent, render, screen } from '@testing-library/react';
import { useBeforeUnloadEvent } from '@/hooks/useBeforeUnloadEvent';
import { useScrollTop } from '@/hooks/useScrollTop';
import { useScopedI18n } from '@/i18n/client';
import { SubscriptionsScreen } from './SubscriptionsScreen';
import { useDeleteProfileHander } from './useDeleteProfileHander';
import { useSubscriptionsHandlers } from './useSubscriptionsHandlers';
import type { Mock } from 'vitest';

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

vi.mock('@/i18n/client', () => ({
    useScopedI18n: vi.fn().mockReturnValue((term: string) => term),
}));

const subscriptions = [
    { id: '1', name: 'Subscription 1', isActive: true },
    { id: '2', name: 'Subscription 2', isActive: false },
];

const useSubscriptionsHandlersResult = {
    subscriptions: subscriptions,
    subscriptionsTouched: false,
    futureCorrespondenceChecked: false,
    updateSubscriptionsState: {
        loading: false,
        error: false,
        updated: false,
    },
    setFutureCorrespondenceChecked: vi.fn(),
    handleSubscriptionChange: vi.fn(),
    handleUnsubscribeFromAll: vi.fn(),
    handleSubscriptionsSave: vi.fn(),
};

vi.mock('./useSubscriptionsHandlers', () => ({
    useSubscriptionsHandlers: vi.fn(() => useSubscriptionsHandlersResult),
}));

const useDeleteProfileHanderResult = {
    deleteAllChecked: false,
    setDeleteAllChecked: vi.fn(),
    deleteProfileState: {
        result: null,
        pending: false,
        error: null,
    },
    handleDeleteProfileAction: vi.fn(),
};

vi.mock('./useDeleteProfileHander', () => ({
    useDeleteProfileHander: vi.fn(() => useDeleteProfileHanderResult),
}));

vi.mock('@/hooks/useBeforeUnloadEvent', () => ({
    useBeforeUnloadEvent: vi.fn(),
}));

vi.mock('@/hooks/useScrollTop', () => ({
    useScrollTop: vi.fn(),
}));

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

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

    describe('scoped i18n', () => {
        it('should recieve correct arguments', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(useScopedI18n).toHaveBeenCalledWith(
                'pages.profile.subscriptionsTab'
            );
        });
    });

    describe('useSubscriptionsHandlers', () => {
        it('should recieve correct arguments', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(useSubscriptionsHandlers).toHaveBeenCalledWith(
                'token',
                subscriptions
            );
        });
    });

    describe('useDeleteProfileHander', () => {
        it('should recieve correct arguments', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(useDeleteProfileHander).toHaveBeenCalledWith('token');
        });
    });

    describe('useBeforeUnloadEvent', () => {
        it('should recieve correct arguments', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(useBeforeUnloadEvent).toHaveBeenCalledWith(
                useSubscriptionsHandlersResult.subscriptionsTouched
            );
        });
    });

    describe('useScrollTop', () => {
        it('should recieve correct arguments', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(useScrollTop).toHaveBeenCalledWith(false);
        });
    });

    describe('subscriptions card', () => {
        it('should render title', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(
                screen.getByText('subscriptionsSection.title')
            ).toBeVisible();
        });

        it('should render subscriptions', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            subscriptions.forEach(item => {
                expect(screen.getByText(item.name)).toBeVisible();
            });
        });

        describe('save changes button', () => {
            it('should be visible', () => {
                render(<SubscriptionsScreen items={subscriptions} />);

                expect(
                    screen.getByText('subscriptionsSection.saveButton')
                ).toBeVisible();
            });

            it('should be disabled by default', () => {
                render(<SubscriptionsScreen items={subscriptions} />);

                expect(
                    screen.getByText('subscriptionsSection.saveButton')
                ).toBeDisabled();
            });

            describe('when subscriptions were touched', () => {
                beforeEach(() => {
                    (useSubscriptionsHandlers as Mock).mockReturnValueOnce({
                        ...useSubscriptionsHandlersResult,
                        subscriptionsTouched: true,
                    });
                });

                it('should be enabled', () => {
                    render(<SubscriptionsScreen items={subscriptions} />);

                    expect(
                        screen.getByText('subscriptionsSection.saveButton')
                    ).toBeEnabled();
                });

                it('should be call handler', () => {
                    render(<SubscriptionsScreen items={subscriptions} />);

                    const button = screen.getByText(
                        'subscriptionsSection.saveButton'
                    );

                    fireEvent.click(button);

                    expect(
                        useSubscriptionsHandlersResult.handleSubscriptionsSave
                    ).toHaveBeenCalled();
                });
            });
        });
    });

    describe('unsusbscribe card', () => {
        it('should render checkbox', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(
                screen.getByRole('checkbox', {
                    name: 'futureCorrespondenceSection.label',
                })
            ).toBeVisible();
        });

        it('checkbox should be unchecked by default', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(
                screen.getByRole('checkbox', {
                    name: 'futureCorrespondenceSection.label',
                    checked: false,
                })
            ).toBeVisible();
        });

        it('should render text', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(
                screen.getByText('futureCorrespondenceSection.label')
            ).toBeVisible();
        });

        describe('unsubscribe button', () => {
            it('should be visible', () => {
                render(<SubscriptionsScreen items={subscriptions} />);

                expect(
                    screen.getByText('futureCorrespondenceSection.saveButton')
                ).toBeVisible();
            });

            it('should be disabled by default', () => {
                render(<SubscriptionsScreen items={subscriptions} />);

                expect(
                    screen.getByText('futureCorrespondenceSection.saveButton')
                ).toBeDisabled();
            });

            describe('when checkbox checked', () => {
                beforeEach(() => {
                    (useSubscriptionsHandlers as Mock).mockReturnValueOnce({
                        ...useSubscriptionsHandlersResult,
                        futureCorrespondenceChecked: true,
                    });
                });

                it('should be enabled', () => {
                    render(<SubscriptionsScreen items={subscriptions} />);

                    expect(
                        screen.getByText(
                            'futureCorrespondenceSection.saveButton'
                        )
                    ).toBeEnabled();
                });

                it('should be call handler', () => {
                    render(<SubscriptionsScreen items={subscriptions} />);

                    const button = screen.getByText(
                        'futureCorrespondenceSection.saveButton'
                    );

                    fireEvent.click(button);

                    expect(
                        useSubscriptionsHandlersResult.handleUnsubscribeFromAll
                    ).toHaveBeenCalled();
                });
            });
        });
    });

    describe('delete profile card', () => {
        it('should render checkbox', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(
                screen.getByRole('checkbox', {
                    name: 'deleteAllSection.label',
                })
            ).toBeVisible();
        });

        it('checkbox should be unchecked by default', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(
                screen.getByRole('checkbox', {
                    name: 'deleteAllSection.label',
                    checked: false,
                })
            ).toBeVisible();
        });

        it('should render text', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(screen.getByText('deleteAllSection.label')).toBeVisible();
        });

        describe('delete profile button', () => {
            it('should be visible', () => {
                render(<SubscriptionsScreen items={subscriptions} />);

                expect(
                    screen.getByText('deleteAllSection.saveButton')
                ).toBeVisible();
            });

            it('should be disabled by default', () => {
                render(<SubscriptionsScreen items={subscriptions} />);

                expect(
                    screen.getByText('deleteAllSection.saveButton')
                ).toBeDisabled();
            });

            describe('when checkbox checked', () => {
                beforeEach(() => {
                    (useDeleteProfileHander as Mock).mockReturnValueOnce({
                        ...useDeleteProfileHanderResult,
                        deleteAllChecked: true,
                    });
                });

                it('should be enabled', () => {
                    render(<SubscriptionsScreen items={subscriptions} />);

                    expect(
                        screen.getByText('deleteAllSection.saveButton')
                    ).toBeEnabled();
                });

                it('should be call handler', () => {
                    render(<SubscriptionsScreen items={subscriptions} />);

                    const button = screen.getByText(
                        'deleteAllSection.saveButton'
                    );

                    fireEvent.click(button);

                    expect(
                        useDeleteProfileHanderResult.handleDeleteProfileAction
                    ).toHaveBeenCalled();
                });
            });
        });
    });

    describe('loading overlay', () => {
        it('should not be visibile', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(
                screen.queryByText('loadingOverlay.altText')
            ).not.toBeInTheDocument();
        });

        describe('when subscriptions are getting updated', () => {
            it('should be visible', () => {
                (useSubscriptionsHandlers as Mock).mockReturnValueOnce({
                    ...useSubscriptionsHandlersResult,
                    updateSubscriptionsState: {
                        ...useSubscriptionsHandlersResult.updateSubscriptionsState,
                        loading: true,
                    },
                });

                render(<SubscriptionsScreen items={subscriptions} />);

                expect(
                    screen.getByText('loadingOverlay.altText')
                ).toBeVisible();
            });
        });

        describe('when profile is getting updated', () => {
            it('should be visible', () => {
                (useDeleteProfileHander as Mock).mockReturnValueOnce({
                    ...useDeleteProfileHanderResult,
                    deleteProfileState: {
                        ...useDeleteProfileHanderResult.deleteProfileState,
                        pending: true,
                    },
                });

                render(<SubscriptionsScreen items={subscriptions} />);

                expect(
                    screen.getByText('loadingOverlay.altText')
                ).toBeVisible();
            });
        });
    });

    describe('success alert', () => {
        it('should not be visible', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(
                screen.queryByText('subscriptionsUpdatedMessage')
            ).not.toBeInTheDocument();
        });

        describe('when subscriptions were updated', () => {
            it('should be visible', () => {
                (useSubscriptionsHandlers as Mock).mockReturnValueOnce({
                    ...useSubscriptionsHandlersResult,
                    updateSubscriptionsState: {
                        ...useSubscriptionsHandlersResult.updateSubscriptionsState,
                        updated: true,
                    },
                });

                render(<SubscriptionsScreen items={subscriptions} />);

                expect(
                    screen.getByText('subscriptionsUpdatedMessage')
                ).toBeVisible();
            });
        });
    });

    describe('error alert', () => {
        it('should not be visible', () => {
            render(<SubscriptionsScreen items={subscriptions} />);

            expect(screen.queryByText('errorMessage')).not.toBeInTheDocument();
        });

        describe('when updating subscriptions resolved with error', () => {
            it('should be visible', () => {
                (useSubscriptionsHandlers as Mock).mockReturnValueOnce({
                    ...useSubscriptionsHandlersResult,
                    updateSubscriptionsState: {
                        ...useSubscriptionsHandlersResult.updateSubscriptionsState,
                        error: true,
                    },
                });

                render(<SubscriptionsScreen items={subscriptions} />);

                expect(screen.getByText('errorMessage')).toBeVisible();
            });
        });

        describe('when deleting profile resolved with error', () => {
            it('should be visible', () => {
                (useDeleteProfileHander as Mock).mockReturnValueOnce({
                    ...useDeleteProfileHanderResult,
                    deleteProfileState: {
                        ...useDeleteProfileHanderResult.deleteProfileState,
                        result: {
                            error: {},
                        },
                    },
                });

                render(<SubscriptionsScreen items={subscriptions} />);

                expect(screen.getByText('errorMessage')).toBeVisible();
            });
        });

        describe('when deleting profile rejected with error', () => {
            it('should be visible', () => {
                (useDeleteProfileHander as Mock).mockReturnValueOnce({
                    ...useDeleteProfileHanderResult,
                    deleteProfileState: {
                        ...useDeleteProfileHanderResult.deleteProfileState,
                        error: true,
                    },
                });

                render(<SubscriptionsScreen items={subscriptions} />);

                expect(screen.getByText('errorMessage')).toBeVisible();
            });
        });
    });

    describe('when profile is deleted', () => {
        it('should render DeletedProfileView', () => {
            (useDeleteProfileHander as Mock).mockReturnValueOnce({
                ...useDeleteProfileHanderResult,
                deleteProfileState: {
                    ...useDeleteProfileHanderResult.deleteProfileState,
                    result: {
                        data: true,
                    },
                },
            });

            render(<SubscriptionsScreen items={subscriptions} />);

            expect(screen.getByText('DeletedProfileView')).toBeVisible();
        });
    });
});
