import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { render, screen, waitFor, fireEvent, act } from '@testing-library/react'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

import Knowledge from '@/pages/Knowledge'

// ── Mock data ──────────────────────────────────────────────────

const mockCategories = [
  {
    id: 'cat-001', name: '技术文档', description: '技术相关文档',
    parent_id: null, icon: '📚', sort_order: 0, item_count: 5,
    children: [], created_at: '2026-01-01T00:00:00Z', updated_at: '2026-01-01T00:00:00Z',
  },
  {
    id: 'cat-002', name: '行业知识', description: '行业相关知识',
    parent_id: null, icon: '🏭', sort_order: 1, item_count: 3,
    children: [], created_at: '2026-01-15T00:00:00Z', updated_at: '2026-01-15T00:00:00Z',
  },
]

const mockItems = {
  items: [
    {
      id: 'item-001', category_id: 'cat-001', title: 'API 认证指南',
      content: 'JWT 认证流程说明...', keywords: ['认证', 'JWT'],
      related_questions: [], priority: 5, status: 'active',
      version: 2, source: 'manual', tags: ['api', 'auth'],
      created_by: 'admin', created_at: '2026-02-01T00:00:00Z', updated_at: '2026-03-01T00:00:00Z',
    },
    {
      id: 'item-002', category_id: 'cat-002', title: '玩具市场趋势 2026',
      content: '2026 年玩具行业趋势分析...', keywords: ['市场', '趋势'],
      related_questions: [], priority: 3, status: 'active',
      version: 1, source: 'import', tags: ['market'],
      created_by: 'admin', created_at: '2026-03-01T00:00:00Z', updated_at: '2026-03-01T00:00:00Z',
    },
  ],
  total: 2, page: 1, page_size: 20,
}

const mockOverview = {
  total_items: 8, active_items: 6, total_categories: 2,
  weekly_new_items: 1, total_references: 45, avg_reference_per_item: 5.6,
  hit_rate: 0.78, injection_rate: 0.65, positive_feedback_rate: 0.92,
  stale_items_count: 1,
}

const mockTrends = { trends: [{ date: '2026-04-01', new_items: 2, references: 10, queries: 25 }] }
const mockTopItems = { items: [] }
const mockQuality = { metrics: [] }
const mockGaps = { gaps: [] }

const server = setupServer()

beforeEach(() => {
  server.listen({ onUnhandledRequest: 'bypass' })
})

afterEach(() => {
  server.close()
})

function renderWithProviders(ui: React.ReactElement) {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  })
  return render(
    <QueryClientProvider client={queryClient}>
      {ui}
    </QueryClientProvider>,
  )
}

function setupKnowledgeHandlers(overrides: Record<string, unknown> = {}) {
  server.use(
    http.get('*/api/v1/knowledge/categories', () => {
      return HttpResponse.json(overrides.categories ?? mockCategories)
    }),
    http.get('*/api/v1/knowledge/items', () => {
      return HttpResponse.json(overrides.items ?? mockItems)
    }),
    http.get('*/api/v1/knowledge/analytics/overview', () => {
      return HttpResponse.json(overrides.overview ?? mockOverview)
    }),
    http.get('*/api/v1/knowledge/analytics/trends', () => {
      return HttpResponse.json(overrides.trends ?? mockTrends)
    }),
    http.get('*/api/v1/knowledge/analytics/top-items', () => {
      return HttpResponse.json(overrides.topItems ?? mockTopItems)
    }),
    http.get('*/api/v1/knowledge/analytics/quality', () => {
      return HttpResponse.json(overrides.quality ?? mockQuality)
    }),
    http.get('*/api/v1/knowledge/analytics/gaps', () => {
      return HttpResponse.json(overrides.gaps ?? mockGaps)
    }),
  )
}

describe('Knowledge', () => {
  // ── Tab structure ─────────────────────────────────────────────

  it('renders all tab labels', () => {
    setupKnowledgeHandlers()
    renderWithProviders(<Knowledge />)

    expect(screen.getByText('知识条目')).toBeInTheDocument()
    expect(screen.getByText('分类管理')).toBeInTheDocument()
    expect(screen.getByText('搜索')).toBeInTheDocument()
    expect(screen.getByText('分析看板')).toBeInTheDocument()
  })

  // ── Items Tab (default) ──────────────────────────────────────

  it('displays items in default tab', async () => {
    setupKnowledgeHandlers()
    renderWithProviders(<Knowledge />)

    await waitFor(() => {
      expect(screen.getByText('API 认证指南')).toBeInTheDocument()
    })
    expect(screen.getByText('玩具市场趋势 2026')).toBeInTheDocument()
  })

  it('displays item status with Chinese labels', async () => {
    setupKnowledgeHandlers()
    renderWithProviders(<Knowledge />)

    await waitFor(() => {
      // status "active" is displayed as "活跃" via statusLabels mapping
      const activeLabels = screen.getAllByText('活跃')
      expect(activeLabels.length).toBeGreaterThanOrEqual(2)
    })
  })

  it('displays item version column', async () => {
    setupKnowledgeHandlers()
    renderWithProviders(<Knowledge />)

    await waitFor(() => {
      expect(screen.getByText('API 认证指南')).toBeInTheDocument()
    })
    // Version numbers in the table
    expect(screen.getByText('2')).toBeInTheDocument()
  })

  it('shows empty state when no items', async () => {
    setupKnowledgeHandlers({
      items: { items: [], total: 0, page: 1, page_size: 20 },
    })
    renderWithProviders(<Knowledge />)

    await waitFor(() => {
      const empties = screen.getAllByText('暂无数据')
      expect(empties.length).toBeGreaterThanOrEqual(1)
    })
  })

  // ── Categories Tab ───────────────────────────────────────────

  it('switches to categories tab and displays categories', async () => {
    setupKnowledgeHandlers()
    renderWithProviders(<Knowledge />)

    await waitFor(() => {
      expect(screen.getByText('API 认证指南')).toBeInTheDocument()
    })

    // Find the tab button (not the panel heading) and click it
    const categoryTabs = screen.getAllByText('分类管理')
    await act(async () => {
      fireEvent.click(categoryTabs[0])
    })

    // Wait for the categories panel to render its heading and tree
    await waitFor(() => {
      // "新建分类" button should appear in the CategoriesPanel toolbar
      expect(screen.getByText('新建分类')).toBeInTheDocument()
    }, { timeout: 3000 })

    // Category names rendered via Tree component inside spans with icon prefix
    // Use stringContaining since the text includes icon emoji prefix
    expect(screen.getByText((content) => content.includes('技术文档'))).toBeInTheDocument()
    expect(screen.getByText((content) => content.includes('行业知识'))).toBeInTheDocument()
  })

  it('shows empty categories state', async () => {
    setupKnowledgeHandlers({ categories: [] })
    renderWithProviders(<Knowledge />)

    // Wait for items tab to load first
    await waitFor(() => {
      expect(screen.getByText('API 认证指南')).toBeInTheDocument()
    })

    // Switch to categories tab
    const categoryTabs = screen.getAllByText('分类管理')
    await act(async () => {
      fireEvent.click(categoryTabs[0])
    })

    // The CategoriesPanel should show "暂无分类，请新建一个" for empty state
    await waitFor(() => {
      expect(screen.getByText('暂无分类，请新建一个')).toBeInTheDocument()
    }, { timeout: 3000 })
  })

  // ── Analytics Tab ────────────────────────────────────────────

  it('switches to analytics tab and shows overview stats', async () => {
    setupKnowledgeHandlers()
    renderWithProviders(<Knowledge />)

    const analyticsTab = screen.getByText('分析看板')
    await act(async () => {
      fireEvent.click(analyticsTab)
    })

    await waitFor(() => {
      expect(screen.getByText('总条目数')).toBeInTheDocument()
    })
    expect(screen.getByText('活跃条目')).toBeInTheDocument()
    expect(screen.getByText('分类数')).toBeInTheDocument()
    expect(screen.getByText('本周新增')).toBeInTheDocument()
  })

  it('displays analytics numbers', async () => {
    setupKnowledgeHandlers()
    renderWithProviders(<Knowledge />)

    const analyticsTab = screen.getByText('分析看板')
    await act(async () => {
      fireEvent.click(analyticsTab)
    })

    await waitFor(() => {
      // total_items: 8
      expect(screen.getByText('8')).toBeInTheDocument()
    })
  })

  // ── Error Handling ───────────────────────────────────────────

  it('shows empty on API failure', async () => {
    server.use(
      http.get('*/api/v1/knowledge/categories', () => {
        return HttpResponse.json(
          { error: 'internal_error', message: '数据库错误' },
          { status: 500 },
        )
      }),
      http.get('*/api/v1/knowledge/items', () => {
        return HttpResponse.json(
          { error: 'internal_error', message: '数据库错误' },
          { status: 500 },
        )
      }),
    )
    renderWithProviders(<Knowledge />)

    await waitFor(() => {
      const empties = screen.getAllByText('暂无数据')
      expect(empties.length).toBeGreaterThanOrEqual(1)
    })
  })

  // ── Loading State ────────────────────────────────────────────

  it('shows loading spinner', async () => {
    server.use(
      http.get('*/api/v1/knowledge/categories', async () => {
        await new Promise(resolve => setTimeout(resolve, 500))
        return HttpResponse.json(mockCategories)
      }),
      http.get('*/api/v1/knowledge/items', async () => {
        await new Promise(resolve => setTimeout(resolve, 500))
        return HttpResponse.json(mockItems)
      }),
    )
    renderWithProviders(<Knowledge />)
    expect(document.querySelector('.ant-spin')).toBeTruthy()
  })

  // ── Item Tags ────────────────────────────────────────────────

  it('displays item tags in table', async () => {
    setupKnowledgeHandlers()
    renderWithProviders(<Knowledge />)

    await waitFor(() => {
      expect(screen.getByText('api')).toBeInTheDocument()
    })
    expect(screen.getByText('auth')).toBeInTheDocument()
    expect(screen.getByText('market')).toBeInTheDocument()
  })
})
