import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen } from '../../../test/utils'
import { RoleGate } from '../RoleGate'
import { useAuthStore } from '../../../lib/auth'
import type { UserRole } from '../../../types/api'
import { createMockUser } from '../../../test/utils'

// Mock the auth store
vi.mock('../../../lib/auth', () => ({
  useAuthStore: vi.fn()
}))

const mockUseAuthStore = vi.mocked(useAuthStore)

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

  it('renders children when user has allowed role', () => {
    const mockUser = createMockUser({ role: 'reviewer' as UserRole })
    mockUseAuthStore.mockReturnValue({
      user: mockUser
    })

    render(
      <RoleGate allowedRoles={['reviewer' as UserRole]}>
        <div>Protected content</div>
      </RoleGate>
    )

    expect(screen.getByText('Protected content')).toBeInTheDocument()
  })

  it('renders children when user is admin (always allowed)', () => {
    const mockUser = createMockUser({ role: 'admin' as UserRole })
    mockUseAuthStore.mockReturnValue({
      user: mockUser
    })

    render(
      <RoleGate allowedRoles={['client' as UserRole]}>
        <div>Protected content</div>
      </RoleGate>
    )

    expect(screen.getByText('Protected content')).toBeInTheDocument()
  })

  it('shows access denied when user role is not allowed', () => {
    const mockUser = createMockUser({ role: 'client' as UserRole })
    mockUseAuthStore.mockReturnValue({
      user: mockUser
    })

    render(
      <RoleGate allowedRoles={['reviewer' as UserRole]}>
        <div>Protected content</div>
      </RoleGate>
    )

    expect(screen.getByText('Access Denied')).toBeInTheDocument()
    expect(screen.getByText("You don't have permission to access this page.")).toBeInTheDocument()
    expect(screen.queryByText('Protected content')).not.toBeInTheDocument()
  })

  it('shows access denied when no user is present', () => {
    mockUseAuthStore.mockReturnValue({
      user: null
    })

    render(
      <RoleGate allowedRoles={['client' as UserRole]}>
        <div>Protected content</div>
      </RoleGate>
    )

    expect(screen.getByText('Access Denied')).toBeInTheDocument()
    expect(screen.getByText("You don't have permission to access this page.")).toBeInTheDocument()
    expect(screen.queryByText('Protected content')).not.toBeInTheDocument()
  })

  it('allows access when user role is in allowed roles list', () => {
    const mockUser = createMockUser({ role: 'reviewer' as UserRole })
    mockUseAuthStore.mockReturnValue({
      user: mockUser
    })

    render(
      <RoleGate allowedRoles={['client' as UserRole, 'reviewer' as UserRole]}>
        <div>Multi-role protected content</div>
      </RoleGate>
    )

    expect(screen.getByText('Multi-role protected content')).toBeInTheDocument()
  })

  it('denies access when user role is not in allowed roles list', () => {
    const mockUser = createMockUser({ role: 'client' as UserRole })
    mockUseAuthStore.mockReturnValue({
      user: mockUser
    })

    render(
      <RoleGate allowedRoles={['reviewer' as UserRole]}>
        <div>Reviewer only content</div>
      </RoleGate>
    )

    expect(screen.getByText('Access Denied')).toBeInTheDocument()
    expect(screen.queryByText('Reviewer only content')).not.toBeInTheDocument()
  })

  it('has consistent styling for access denied message', () => {
    const mockUser = createMockUser({ role: 'client' as UserRole })
    mockUseAuthStore.mockReturnValue({
      user: mockUser
    })

    render(
      <RoleGate allowedRoles={['admin' as UserRole]}>
        <div>Admin content</div>
      </RoleGate>
    )

    const container = screen.getByText('Access Denied').closest('.min-h-screen')!
    expect(container).toHaveClass('min-h-screen', 'flex', 'items-center', 'justify-center')
    
    const heading = screen.getByText('Access Denied')
    expect(heading).toHaveClass('text-2xl', 'font-bold', 'text-gray-900', 'mb-4')
    
    const description = screen.getByText("You don't have permission to access this page.")
    expect(description).toHaveClass('text-gray-600')
  })
})