import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { MemoryRouter, Route, Routes, useNavigate, useParams, useLocation } from 'react-router-dom';
import AnnouncementDetail from './AnnouncementDetail';
import * as announcementApi from '../api/announcement';

// Mock API 模块
jest.mock('../api/announcement');

// Mock 路由钩子
const mockNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useNavigate: () => mockNavigate,
  useParams: jest.fn(),
  useLocation: jest.fn(),
}));

describe('AnnouncementDetail 组件', () => {
  const mockAnnouncement = {
    id: 1,
    title: '测试公告标题',
    content: '这是测试公告内容\n这是第二行内容',
    createTime: '2023-01-01T00:00:00Z',
  };

  beforeEach(() => {
    mockNavigate.mockClear();

    // 设置模拟的 API 响应
    announcementApi.getAnnouncementDetail.mockResolvedValue({
      data: {
        code: 200,
        data: {
          announcement: mockAnnouncement,
        },
      },
    });

    // 模拟钩子
    useParams.mockReturnValue({ id: '1' });
    useLocation.mockReturnValue({ state: { fromTab: 'announcement' } });
  });

  const renderComponent = () => {
    return render(
      <MemoryRouter initialEntries={['/announcement/1']}>
        <Routes>
          <Route path="/announcement/:id" element={<AnnouncementDetail />} />
          <Route path="/dashboard/announcement" element={<div>公告列表</div>} />
        </Routes>
      </MemoryRouter>
    );
  };

  it('应该正确加载和显示公告详情', async () => {
    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('测试公告标题')).toBeInTheDocument();
      expect(screen.getByText('这是测试公告内容')).toBeInTheDocument();
      expect(screen.getByText('这是第二行内容')).toBeInTheDocument();
    });
  });

  it('应该处理公告加载失败的情况', async () => {
    announcementApi.getAnnouncementDetail.mockResolvedValue({
      data: { code: 404, message: '公告不存在' },
    });

    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('公告不存在')).toBeInTheDocument();
    });
  });

  it('应该能够返回公告区', async () => {
    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('测试公告标题')).toBeInTheDocument();
    });

    fireEvent.click(screen.getByRole('button', { name: /返回/i }));

    // 检查是否导航回公告区
    expect(mockNavigate).toHaveBeenCalledWith('/dashboard/announcement');
  });

  it('应该显示加载错误时的UI', async () => {
    announcementApi.getAnnouncementDetail.mockRejectedValue(new Error('网络错误'));

    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('获取公告详情失败')).toBeInTheDocument();
    });
  });

  // 边界测试 - 测试公告ID不存在
  it('应该处理不存在的公告ID', async () => {
    announcementApi.getAnnouncementDetail.mockResolvedValue({
      data: { code: 404, message: '公告不存在' },
    });

    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('公告不存在')).toBeInTheDocument();
    });
  });

  // 边界测试 - 测试其他API错误
  it('应该处理服务器错误', async () => {
    announcementApi.getAnnouncementDetail.mockResolvedValue({
      data: { code: 500, message: '服务器错误' },
    });

    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('服务器错误')).toBeInTheDocument();
    });
  });
});
