import React from 'react';
import { render, screen } from '@testing-library/react';
import { ROUTE_TOOLS } from 'src/constants';
import {
    ToolsEntry,
    PubSongChangesEntry,
    ContentModerationEntry,
} from '../index';

jest.mock('@theorchard/suite-frontend', () => ({
    initApplicationModule: jest.fn(),
    NotFoundPage: () => <div data-testid="not-found-page" />,
}));

jest.mock('@theorchard/suite-components', () => ({
    LoadingPageIndicator: () => <div data-testid="loading-page-indicator" />,
}));

jest.mock('react-router-dom', () => ({
    Redirect: ({ to }: { to: string }) => (
        <div data-testid="redirect">{to}</div>
    ),
}));

jest.mock('../utils/permissions', () => ({
    hasToolsModuleAccess: jest.fn(),
    useToolsAccess: jest.fn(),
}));

jest.mock('src/pages/contentModerationPage', () => () => (
    <div data-testid="content-moderation-page" />
));

jest.mock('src/pages/pubSongChangesPage', () => () => (
    <div data-testid="pub-song-changes-page" />
));

jest.mock('./pages/toolsPage', () => () => <div data-testid="tools-page" />, {
    virtual: true,
});

jest.mock('../pages/toolsPage', () => () => <div data-testid="tools-page" />);

jest.mock('../styles', () => {});

import { useToolsAccess } from '../utils/permissions';

const mockUseToolsAccess = useToolsAccess as jest.Mock;

const makeAccess = (overrides: Partial<ReturnType<typeof useToolsAccess>>) => ({
    canAccessToolsByRole: () => false,
    canAccessContentModeration: false,
    loading: false,
    hasCardAccess: () => false,
    ...overrides,
});

afterEach(() => {
    jest.resetAllMocks();
});

describe('ToolsEntry', () => {
    test('renders LoadingPageIndicator while loading', () => {
        mockUseToolsAccess.mockReturnValue(makeAccess({ loading: true }));
        render(<ToolsEntry />);
        expect(
            screen.getByTestId('loading-page-indicator')
        ).toBeInTheDocument();
    });

    test('renders ToolsPage when user has a tools role', () => {
        mockUseToolsAccess.mockReturnValue(
            makeAccess({ canAccessToolsByRole: () => true })
        );
        render(<ToolsEntry />);
        expect(screen.getByTestId('tools-page')).toBeInTheDocument();
    });

    test('renders ToolsPage when user has PP content moderation access', () => {
        mockUseToolsAccess.mockReturnValue(
            makeAccess({ canAccessContentModeration: true })
        );
        render(<ToolsEntry />);
        expect(screen.getByTestId('tools-page')).toBeInTheDocument();
    });

    test('renders NotFoundPage when user has no role and no PP access', () => {
        mockUseToolsAccess.mockReturnValue(makeAccess({}));
        render(<ToolsEntry />);
        expect(screen.getByTestId('not-found-page')).toBeInTheDocument();
    });
});

describe('PubSongChangesEntry', () => {
    test('renders PubSongChangesPage when user has the publishing role', () => {
        mockUseToolsAccess.mockReturnValue(
            makeAccess({ canAccessToolsByRole: () => true })
        );
        render(<PubSongChangesEntry />);
        expect(screen.getByTestId('pub-song-changes-page')).toBeInTheDocument();
    });

    test('redirects to ROUTE_TOOLS when user lacks the publishing role', () => {
        mockUseToolsAccess.mockReturnValue(makeAccess({}));
        render(<PubSongChangesEntry />);
        expect(screen.getByTestId('redirect')).toHaveTextContent(ROUTE_TOOLS);
    });
});

describe('ContentModerationEntry', () => {
    test('renders LoadingPageIndicator while loading', () => {
        mockUseToolsAccess.mockReturnValue(makeAccess({ loading: true }));
        render(<ContentModerationEntry />);
        expect(
            screen.getByTestId('loading-page-indicator')
        ).toBeInTheDocument();
    });

    test('renders ContentModerationPage when PP grants access', () => {
        mockUseToolsAccess.mockReturnValue(
            makeAccess({ canAccessContentModeration: true })
        );
        render(<ContentModerationEntry />);
        expect(
            screen.getByTestId('content-moderation-page')
        ).toBeInTheDocument();
    });

    test('redirects to ROUTE_TOOLS when PP denies access', () => {
        mockUseToolsAccess.mockReturnValue(makeAccess({}));
        render(<ContentModerationEntry />);
        expect(screen.getByTestId('redirect')).toHaveTextContent(ROUTE_TOOLS);
    });
});
