import { describe, it, expect, beforeEach, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { AppRouter } from './index';
import { useAuthStore } from '@/features/auth/store/authStore';

// Mock the stores
vi.mock('@/features/auth/store/authStore', () => ({
  useAuthStore: vi.fn(),
}));

// Mock lazy components
vi.mock('@/components/ui/LazyComponent', () => ({
  LazyLogin: () => <div>Login Page</div>,
  LazyRegister: () => <div>Register Page</div>,
  LazyForgotPassword: () => <div>Forgot Password Page</div>,
  LazyDashboard: () => <div>Dashboard Page</div>,
  LazyChat: () => <div>Chat Page</div>,
  LazyLibrary: () => <div>Library Page</div>,
  LazyProfile: () => <div>Profile Page</div>,
  LazySettings: () => <div>Settings Page</div>,
  LazyNotFound: () => <div>404 Not Found</div>,
  LazyServerError: () => <div>500 Server Error</div>,
}));

// Mock Layout component
vi.mock('@/components/layout/Layout', () => ({
  Layout: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="layout">{children}</div>
  ),
}));

// Mock LoadingSpinner
vi.mock('@/components/ui/loading-spinner', () => ({
  LoadingSpinner: () => <div>Loading...</div>,
}));

describe('AppRouter', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('Public Routes', () => {
    it('should render login page for /login route when not authenticated', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: false,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/login']}>
          <AppRouter />
        </MemoryRouter>,
      );

      expect(screen.getByText('Login Page')).toBeInTheDocument();
    });

    it('should redirect to dashboard when authenticated user tries to access login', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: true,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/login']}>
          <AppRouter />
        </MemoryRouter>,
      );

      // Should redirect to dashboard (mocked as Dashboard Page)
      expect(screen.getByText('Dashboard Page')).toBeInTheDocument();
    });

    it('should render register page for /register route when not authenticated', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: false,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/register']}>
          <AppRouter />
        </MemoryRouter>,
      );

      expect(screen.getByText('Register Page')).toBeInTheDocument();
    });
  });

  describe('Protected Routes', () => {
    it('should render dashboard page when authenticated', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: true,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/dashboard']}>
          <AppRouter />
        </MemoryRouter>,
      );

      expect(screen.getByTestId('layout')).toBeInTheDocument();
      expect(screen.getByText('Dashboard Page')).toBeInTheDocument();
    });

    it('should redirect to login when not authenticated user tries to access protected route', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: false,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/dashboard']}>
          <AppRouter />
        </MemoryRouter>,
      );

      // Should redirect to login
      expect(screen.getByText('Login Page')).toBeInTheDocument();
    });

    it('should show loading spinner when checking authentication', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: false,
        isLoading: true,
      } as any);

      render(
        <MemoryRouter initialEntries={['/dashboard']}>
          <AppRouter />
        </MemoryRouter>,
      );

      expect(screen.getByText('Loading...')).toBeInTheDocument();
    });

    it('should render chat page when authenticated', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: true,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/chat']}>
          <AppRouter />
        </MemoryRouter>,
      );

      expect(screen.getByTestId('layout')).toBeInTheDocument();
      expect(screen.getByText('Chat Page')).toBeInTheDocument();
    });

    it('should render library page when authenticated', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: true,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/library']}>
          <AppRouter />
        </MemoryRouter>,
      );

      expect(screen.getByTestId('layout')).toBeInTheDocument();
      expect(screen.getByText('Library Page')).toBeInTheDocument();
    });
  });

  describe('Error Routes', () => {
    it('should render 404 page for /404 route', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: false,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/404']}>
          <AppRouter />
        </MemoryRouter>,
      );

      expect(screen.getByText('404 Not Found')).toBeInTheDocument();
    });

    it('should render 500 page for /500 route', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: false,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/500']}>
          <AppRouter />
        </MemoryRouter>,
      );

      expect(screen.getByText('500 Server Error')).toBeInTheDocument();
    });

    it('should redirect to 404 for unknown routes', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: false,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/unknown-route']}>
          <AppRouter />
        </MemoryRouter>,
      );

      expect(screen.getByText('404 Not Found')).toBeInTheDocument();
    });
  });

  describe('Default Routes', () => {
    it('should redirect root path to dashboard when authenticated', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: true,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/']}>
          <AppRouter />
        </MemoryRouter>,
      );

      expect(screen.getByText('Dashboard Page')).toBeInTheDocument();
    });

    it('should redirect root path to login when not authenticated', () => {
      vi.mocked(useAuthStore).mockReturnValue({
        isAuthenticated: false,
        isLoading: false,
      } as any);

      render(
        <MemoryRouter initialEntries={['/']}>
          <AppRouter />
        </MemoryRouter>,
      );

      // Should redirect to dashboard, which then redirects to login
      expect(screen.getByText('Login Page')).toBeInTheDocument();
    });
  });
});
