import { render, screen, waitFor } from '@testing-library/react'
import { describe, expect, it, vi, beforeEach } from 'vitest'

import { SettingsPage } from './SettingsPage'
import type { SystemSettings } from '@/services/settings'

vi.mock('@ant-design/icons', () => ({
  SafetyOutlined: () => <span>safety</span>,
  SettingOutlined: () => <span>setting</span>,
  EnvironmentOutlined: () => <span>environment</span>,
}))

vi.mock('@/services/settings', () => ({
  getSettings: vi.fn(),
}))

const mockSettings: SystemSettings = {
  system: {
    name: '用户管理系统',
    version: '1.0.0',
    environment: 'Production',
    description: '基于 Go + React 的现代化用户管理系统',
  },
  security: {
    password_min_length: 8,
    password_require_uppercase: true,
    password_require_lowercase: true,
    password_require_numbers: true,
    password_require_symbols: true,
    password_history: 5,
    totp_enabled: true,
    login_fail_lock: true,
    login_fail_threshold: 5,
    login_fail_duration: 30,
    session_timeout: 86400,
    device_trust_duration: 2592000,
  },
  features: {
    email_verification: true,
    phone_verification: false,
    oauth_providers: ['GitHub', 'Google'],
    sso_enabled: false,
    operation_log_enabled: true,
    login_log_enabled: true,
    data_export_enabled: true,
    data_import_enabled: true,
  },
}

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

  it('renders page header with title and description', async () => {
    const { getSettings } = await import('@/services/settings')
    vi.mocked(getSettings).mockResolvedValue(mockSettings)

    render(<SettingsPage />)

    await waitFor(() => {
      expect(screen.getByText('安全设置')).toBeInTheDocument()
    })
    expect(screen.getByText('系统设置')).toBeInTheDocument()
    expect(screen.getByText('查看当前系统配置和功能开关状态')).toBeInTheDocument()
  })

  it('renders security settings section', async () => {
    const { getSettings } = await import('@/services/settings')
    vi.mocked(getSettings).mockResolvedValue(mockSettings)

    render(<SettingsPage />)

    await waitFor(() => {
      expect(screen.getByText('安全设置')).toBeInTheDocument()
    })
    expect(screen.getByText('密码最小长度')).toBeInTheDocument()
    expect(screen.getByText('密码必须包含大写字母')).toBeInTheDocument()
    expect(screen.getByText('密码必须包含小写字母')).toBeInTheDocument()
    expect(screen.getByText('密码必须包含数字')).toBeInTheDocument()
    expect(screen.getByText('密码必须包含特殊字符')).toBeInTheDocument()
  })

  it('renders feature toggles section', async () => {
    const { getSettings } = await import('@/services/settings')
    vi.mocked(getSettings).mockResolvedValue(mockSettings)

    render(<SettingsPage />)

    await waitFor(() => {
      expect(screen.getByText('功能开关')).toBeInTheDocument()
    })
    expect(screen.getByText('邮箱验证')).toBeInTheDocument()
    expect(screen.getByText('手机验证')).toBeInTheDocument()
    expect(screen.getByText('OAuth 提供商')).toBeInTheDocument()
    expect(screen.getByText('GitHub, Google')).toBeInTheDocument()
    expect(screen.getByText('SSO 单点登录')).toBeInTheDocument()
    expect(screen.getByText('操作日志')).toBeInTheDocument()
    expect(screen.getByText('登录日志')).toBeInTheDocument()
    expect(screen.getByText('数据导出')).toBeInTheDocument()
    expect(screen.getByText('数据导入')).toBeInTheDocument()
  })

  it('renders system information section', async () => {
    const { getSettings } = await import('@/services/settings')
    vi.mocked(getSettings).mockResolvedValue(mockSettings)

    render(<SettingsPage />)

    await waitFor(() => {
      expect(screen.getByText('系统信息')).toBeInTheDocument()
    })
    expect(screen.getByText('系统名称')).toBeInTheDocument()
    expect(screen.getByText('用户管理系统')).toBeInTheDocument()
    expect(screen.getByText('版本号')).toBeInTheDocument()
    expect(screen.getByText('1.0.0')).toBeInTheDocument()
    expect(screen.getByText('运行环境')).toBeInTheDocument()
    expect(screen.getByText('Production')).toBeInTheDocument()
    expect(screen.getByText('系统描述')).toBeInTheDocument()
    expect(screen.getByText('基于 Go + React 的现代化用户管理系统')).toBeInTheDocument()
  })

  it('renders password history setting', async () => {
    const { getSettings } = await import('@/services/settings')
    vi.mocked(getSettings).mockResolvedValue(mockSettings)

    render(<SettingsPage />)

    await waitFor(() => {
      expect(screen.getByText('密码历史记录')).toBeInTheDocument()
    })
    expect(screen.getByText(/最近 5 次$/)).toBeInTheDocument()
  })

  it('renders TOTP setting', async () => {
    const { getSettings } = await import('@/services/settings')
    vi.mocked(getSettings).mockResolvedValue(mockSettings)

    render(<SettingsPage />)

    await waitFor(() => {
      expect(screen.getByText('TOTP 两步验证')).toBeInTheDocument()
    })
    const totpEnabled = screen.getAllByText('已启用')
    expect(totpEnabled.length).toBeGreaterThan(0)
  })

  it('shows readonly notice in header actions', async () => {
    const { getSettings } = await import('@/services/settings')
    vi.mocked(getSettings).mockResolvedValue(mockSettings)

    render(<SettingsPage />)

    await waitFor(() => {
      expect(screen.getByText('配置更新请联系管理员')).toBeInTheDocument()
    })
  })

  it('shows loading state while fetching settings', async () => {
    const { getSettings } = await import('@/services/settings')
    // Don't resolve the promise - keep it pending to show loading state
    vi.mocked(getSettings).mockImplementation(() => new Promise(() => {}))

    render(<SettingsPage />)

    // Should show loading spinner
    expect(document.querySelector('.ant-spin')).toBeInTheDocument()
  })

  it('shows error state when API fails', async () => {
    const { getSettings } = await import('@/services/settings')
    vi.mocked(getSettings).mockRejectedValue(new Error('网络错误'))

    render(<SettingsPage />)

    await waitFor(() => {
      expect(screen.getByText('网络错误')).toBeInTheDocument()
    })
  })
})
