import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { VideoFileList } from '../VideoFileList';
import { VideoFileInfo } from '../../../types/frame-extractor';

describe('VideoFileList', () => {
  const mockOnRemoveVideo = vi.fn();
  const mockOnPreviewVideo = vi.fn();

  const validVideoFile: VideoFileInfo = {
    path: '/test/video1.mp4',
    filename: 'video1.mp4',
    size: 1024 * 1024 * 100, // 100MB
    duration: 120.5, // 2 minutes 30.5 seconds
    width: 1920,
    height: 1080,
    fps: 30.0,
    format: 'mp4',
    is_valid: true,
    error_message: undefined,
  };

  const invalidVideoFile: VideoFileInfo = {
    path: '/test/invalid.mp4',
    filename: 'invalid.mp4',
    size: 1024,
    duration: 0,
    width: 0,
    height: 0,
    fps: 0,
    format: '',
    is_valid: false,
    error_message: '无法读取视频信息',
  };

  const defaultProps = {
    videos: [validVideoFile, invalidVideoFile],
    isScanning: false,
    onRemoveVideo: mockOnRemoveVideo,
    onPreviewVideo: mockOnPreviewVideo,
  };

  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders video file list with header', () => {
    render(<VideoFileList {...defaultProps} />);

    expect(screen.getByText('视频文件列表')).toBeInTheDocument();
    expect(screen.getByText('2 个文件')).toBeInTheDocument();
  });

  it('displays valid video file information correctly', () => {
    render(<VideoFileList {...defaultProps} />);

    expect(screen.getByText('video1.mp4')).toBeInTheDocument();
    expect(screen.getByText('02:00')).toBeInTheDocument(); // Duration formatted
    expect(screen.getByText('1920×1080')).toBeInTheDocument(); // Resolution
    expect(screen.getByText('100.00 MB')).toBeInTheDocument(); // File size
    expect(screen.getByText('30.0 fps')).toBeInTheDocument(); // Frame rate
    expect(screen.getByText('MP4')).toBeInTheDocument(); // Format badge
  });

  it('displays invalid video file with error message', () => {
    render(<VideoFileList {...defaultProps} />);

    expect(screen.getByText('invalid.mp4')).toBeInTheDocument();
    expect(screen.getByText('无法读取视频信息')).toBeInTheDocument();
  });

  it('shows scanning state when isScanning is true', () => {
    render(<VideoFileList {...defaultProps} isScanning={true} />);

    expect(screen.getByText('正在扫描视频文件...')).toBeInTheDocument();
  });

  it('shows empty state when no videos and not scanning', () => {
    render(
      <VideoFileList
        {...defaultProps}
        videos={[]}
        isScanning={false}
      />
    );

    expect(screen.getByText('暂无视频文件')).toBeInTheDocument();
    expect(screen.getByText('请选择视频文件或文件夹')).toBeInTheDocument();
  });

  it('calls onRemoveVideo when remove button is clicked', () => {
    render(<VideoFileList {...defaultProps} />);

    const removeButtons = screen.getAllByTitle('移除');
    fireEvent.click(removeButtons[0]);

    expect(mockOnRemoveVideo).toHaveBeenCalledWith(0);
  });

  it('calls onPreviewVideo when preview button is clicked for valid video', () => {
    render(<VideoFileList {...defaultProps} />);

    const previewButton = screen.getByTitle('预览');
    fireEvent.click(previewButton);

    expect(mockOnPreviewVideo).toHaveBeenCalledWith(validVideoFile);
  });

  it('does not show preview button for invalid video', () => {
    render(
      <VideoFileList
        {...defaultProps}
        videos={[invalidVideoFile]}
      />
    );

    expect(screen.queryByTitle('预览')).not.toBeInTheDocument();
  });

  it('displays statistics correctly', () => {
    render(<VideoFileList {...defaultProps} />);

    expect(screen.getByText('有效文件：')).toBeInTheDocument();
    expect(screen.getByText('1')).toBeInTheDocument(); // 1 valid file
    expect(screen.getByText('无效文件：')).toBeInTheDocument();
    expect(screen.getByText('1')).toBeInTheDocument(); // 1 invalid file
    expect(screen.getByText('总时长：')).toBeInTheDocument();
    expect(screen.getByText('02:00')).toBeInTheDocument(); // Only valid video duration
    expect(screen.getByText('总大小：')).toBeInTheDocument();
  });

  it('formats file sizes correctly', () => {
    const testVideos: VideoFileInfo[] = [
      { ...validVideoFile, size: 1024, filename: 'small.mp4' }, // 1 KB
      { ...validVideoFile, size: 1024 * 1024, filename: 'medium.mp4' }, // 1 MB
      { ...validVideoFile, size: 1024 * 1024 * 1024, filename: 'large.mp4' }, // 1 GB
    ];

    render(
      <VideoFileList
        {...defaultProps}
        videos={testVideos}
      />
    );

    expect(screen.getByText('1.00 KB')).toBeInTheDocument();
    expect(screen.getByText('1.00 MB')).toBeInTheDocument();
    expect(screen.getByText('1.00 GB')).toBeInTheDocument();
  });

  it('formats duration correctly for different lengths', () => {
    const testVideos: VideoFileInfo[] = [
      { ...validVideoFile, duration: 45, filename: 'short.mp4' }, // 45 seconds
      { ...validVideoFile, duration: 125, filename: 'medium.mp4' }, // 2:05
      { ...validVideoFile, duration: 3665, filename: 'long.mp4' }, // 1:01:05
    ];

    render(
      <VideoFileList
        {...defaultProps}
        videos={testVideos}
      />
    );

    expect(screen.getByText('00:45')).toBeInTheDocument();
    expect(screen.getByText('02:05')).toBeInTheDocument();
    expect(screen.getByText('01:01:05')).toBeInTheDocument();
  });

  it('handles zero values gracefully', () => {
    const zeroVideo: VideoFileInfo = {
      ...validVideoFile,
      duration: 0,
      width: 0,
      height: 0,
      fps: 0,
      size: 0,
    };

    render(
      <VideoFileList
        {...defaultProps}
        videos={[zeroVideo]}
      />
    );

    expect(screen.getByText('00:00')).toBeInTheDocument();
    expect(screen.getByText('未知')).toBeInTheDocument(); // Resolution
    expect(screen.getByText('未知')).toBeInTheDocument(); // FPS
    expect(screen.getByText('0 B')).toBeInTheDocument();
  });

  it('truncates long file paths with title attribute', () => {
    const longPathVideo: VideoFileInfo = {
      ...validVideoFile,
      path: '/very/long/path/to/video/file/that/should/be/truncated/video.mp4',
    };

    render(
      <VideoFileList
        {...defaultProps}
        videos={[longPathVideo]}
      />
    );

    const pathElement = screen.getByTitle(longPathVideo.path);
    expect(pathElement).toBeInTheDocument();
    expect(pathElement).toHaveClass('truncate');
  });

  it('shows correct file count in header', () => {
    render(<VideoFileList {...defaultProps} />);
    expect(screen.getByText('2 个文件')).toBeInTheDocument();

    render(
      <VideoFileList
        {...defaultProps}
        videos={[]}
      />
    );
    expect(screen.getByText('0 个文件')).toBeInTheDocument();
  });

  it('applies hover effects on video items', () => {
    render(<VideoFileList {...defaultProps} />);

    const videoItems = screen.getAllByText('video1.mp4').map(el => 
      el.closest('.hover\\:bg-gray-50')
    ).filter(Boolean);

    expect(videoItems.length).toBeGreaterThan(0);
  });
});
