import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { MemoryRouter, Route, Routes, useNavigate, useLocation } from 'react-router-dom';
import HelpDetail from './HelpDetail';
import * as helpPostApi from '../api/helpPost';
import * as helpCommentApi from '../api/helpComment';

// Mock API 模块
jest.mock('../api/helpPost');
jest.mock('../api/helpComment');

// Mock 路由钩子
const mockNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useNavigate: () => mockNavigate,
  useLocation: jest.fn(),
}));

describe('HelpDetail 组件', () => {
  const mockPost = {
    id: '1',
    title: '测试求助帖',
    content: '这是一个测试求助内容',
    authorId: 'user1',
    createTime: '2023-01-01T00:00:00Z',
    likeCount: 5,
    replyCount: 3,
    isSolved: false,
  };

  const mockComments = [
    {
      id: 'c1',
      content: '测试评论1',
      authorId: 'user2',
      createTime: '2023-01-01T01:00:00Z',
      likeCount: 2,
      replies: [
        {
          id: 'c1r1',
          content: '测试回复1',
          authorId: 'user3',
          createTime: '2023-01-01T02:00:00Z',
          likeCount: 1,
        }
      ]
    }
  ];

  beforeEach(() => {
    // 重置 mock 函数
    mockNavigate.mockClear();
    
    // 设置模拟的 API 响应
    helpPostApi.getHelpPostDetail.mockResolvedValue({
      data: {
        code: 200,
        data: {
          post: mockPost,
          comments: mockComments,
        }
      }
    });

    // 模拟 useLocation
    useLocation.mockReturnValue({
      state: { fromTab: 'help' }
    });

    // 模拟 localStorage
    Storage.prototype.getItem = jest.fn((key) => {
      if (key === 'username') return 'testuser';
      return null;
    });
  });

  const renderComponent = () => {
    return render(
      <MemoryRouter initialEntries={['/help/1']}>
        <Routes>
          <Route path="/help/:id" element={<HelpDetail />} />
          {/* 添加一个模拟的求助列表路由用于导航测试 */}
          <Route path="/dashboard/help" element={<div>求助列表</div>} />
        </Routes>
      </MemoryRouter>
    );
  };

  it('应该正确加载和显示求助帖详情', async () => {
    renderComponent();

    // 检查加载状态
    expect(screen.getByText('加载中...')).toBeInTheDocument();

    // 等待数据加载完成
    await waitFor(() => {
      expect(screen.getByText('测试求助帖')).toBeInTheDocument();
      expect(screen.getByText('这是一个测试求助内容')).toBeInTheDocument();
      expect(screen.getByText('user1')).toBeInTheDocument();
    });
  });

  it('应该能够点赞帖子', async () => {
    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('测试求助帖')).toBeInTheDocument();
    });

    fireEvent.click(screen.getByText(/点赞 \(5\)/));

    await waitFor(() => {
      expect(helpPostApi.likeHelpPost).toHaveBeenCalledWith('1');
    });
  });

  it('应该能够提交评论', async () => {
  renderComponent();

  await waitFor(() => {
    expect(screen.getByText('测试求助帖')).toBeInTheDocument();
  });

  const commentInput = screen.getByPlaceholderText('写下你的评论...');
  fireEvent.change(commentInput, { target: { value: '新评论' } });
  fireEvent.click(screen.getByText('发表评论'));

  await waitFor(() => {
    expect(helpPostApi.addHelpPostComment).toHaveBeenCalled();
    
    const calledArgs = helpPostApi.addHelpPostComment.mock.calls[0];
    expect(calledArgs[0]).toBe('1'); // postId
    const formData = calledArgs[1];
    
    expect(formData instanceof FormData).toBe(true);
    expect(formData.get('authorId')).toBe('testuser');
    expect(formData.get('content')).toBe('新评论');
  });
});
  it('应该能够点赞评论', async () => {
    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('测试评论1')).toBeInTheDocument();
    });

    fireEvent.click(screen.getAllByText(/👍 \(2\)/)[0]);

    await waitFor(() => {
      expect(helpCommentApi.likeHelpPostComment).toHaveBeenCalledWith('c1');
    });
  });

  it('应该能够打开和关闭回复模态框', async () => {
    renderComponent();

    await waitFor(() => {
      expect(screen.getByText('测试评论1')).toBeInTheDocument();
    });

    // 点击回复按钮
    fireEvent.click(screen.getAllByText('回复')[0]);

    // 检查模态框是否打开
    await waitFor(() => {
      expect(screen.getByText('回复 @user2')).toBeInTheDocument();
    });

    // 点击关闭按钮
    fireEvent.click(screen.getByText('×'));

    // 检查模态框是否关闭
    await waitFor(() => {
      expect(screen.queryByText('回复 @user2')).not.toBeInTheDocument();
    });
  });

  it('应该能够返回求助区', async () => {
    renderComponent();
  
    await waitFor(() => {
      expect(screen.getByText('测试求助帖')).toBeInTheDocument();
    });
  
    fireEvent.click(screen.getByRole('button', { name: /返回/i }));
  
    // 修正后的断言（不再验证 state）
    expect(mockNavigate).toHaveBeenCalledWith('/dashboard/help');
  });
});