/* @vitest-environment jsdom */

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

import type { EditorAsset } from './ImageCanvasEditorTypes';
import { ImageCanvasAssetRowView } from './ImageCanvasAssetRowView';

function createAsset(overrides: Partial<EditorAsset> = {}): EditorAsset {
  return {
    id: 'asset-1',
    label: '账号素材A',
    src: '/creation-type-references/puzzle.webp',
    width: 640,
    height: 512,
    folderId: 'project',
    sourceKind: 'uploaded',
    sourceType: 'uploaded',
    persisted: true,
    ...overrides,
  };
}

function renderAssetRow({
  asset = createAsset(),
  isAssetSelectionMode = false,
  selectedAssetIds = new Set<string>(),
  renamingAsset = null,
  suppressAssetClick = false,
  addAssetLayer = vi.fn(),
  toggleAssetSelected = vi.fn(),
  commitAssetRename = vi.fn(),
}: {
  asset?: EditorAsset;
  isAssetSelectionMode?: boolean;
  selectedAssetIds?: Set<string>;
  renamingAsset?: { assetId: string; value: string } | null;
  suppressAssetClick?: boolean;
  addAssetLayer?: (asset: EditorAsset) => void;
  toggleAssetSelected?: (assetId: string) => void;
  commitAssetRename?: (asset: EditorAsset) => void;
} = {}) {
  const props = {
    asset,
    assetPointerDragRef: { current: null },
    suppressAssetClickRef: { current: suppressAssetClick },
    isAssetSelectionMode,
    selectedAssetIds,
    renamingAsset,
    setRenamingAsset: vi.fn(),
    setUploadDropTarget: vi.fn(),
    setAssetPointerDrag: vi.fn(),
    setSelectedAssetIds: vi.fn(),
    updateAssetMoveDropFolder: vi.fn(),
    addUploadedFiles: vi.fn(),
    moveAssetToFolder: vi.fn(),
    startRenamingAsset: vi.fn(),
    commitAssetRename,
    deleteUploadedAsset: vi.fn(),
    toggleAssetSelected,
    addAssetLayer,
  };

  render(<ImageCanvasAssetRowView {...props} />);
  return props;
}

describe('ImageCanvasAssetRowView', () => {
  it('adds the asset to the canvas in normal mode', () => {
    const addAssetLayer = vi.fn();
    const asset = createAsset();
    renderAssetRow({ asset, addAssetLayer });

    fireEvent.click(screen.getByRole('button', { name: '添加账号素材A' }));

    expect(addAssetLayer).toHaveBeenCalledWith(asset);
  });

  it('selects the asset instead of adding it in selection mode', () => {
    const addAssetLayer = vi.fn();
    const toggleAssetSelected = vi.fn();
    renderAssetRow({
      isAssetSelectionMode: true,
      addAssetLayer,
      toggleAssetSelected,
    });

    fireEvent.click(screen.getByRole('button', { name: '选择素材账号素材A' }));

    expect(toggleAssetSelected).toHaveBeenCalledWith('asset-1');
    expect(addAssetLayer).not.toHaveBeenCalled();
  });

  it('renders rename input and commits with Enter', () => {
    const commitAssetRename = vi.fn();
    renderAssetRow({
      renamingAsset: { assetId: 'asset-1', value: '主视觉素材' },
      commitAssetRename,
    });

    const input = screen.getByLabelText('重命名素材账号素材A');
    fireEvent.keyDown(input, { key: 'Enter' });

    expect(input.className).toContain('platform-text-field');
    expect(input.className).toContain('image-canvas-editor__asset-rename-input');
    expect(commitAssetRename).toHaveBeenCalledWith(
      expect.objectContaining({ id: 'asset-1' }),
    );
  });

  it('keeps uploading assets disabled and shows progress', () => {
    const addAssetLayer = vi.fn();
    renderAssetRow({
      asset: createAsset({
        uploadStatus: 'uploading',
        uploadProgress: 42,
        uploadMessage: '正在上传',
      }),
      addAssetLayer,
    });

    fireEvent.click(screen.getByRole('button', { name: '上传中账号素材A' }));

    expect(addAssetLayer).not.toHaveBeenCalled();
    expect(screen.getAllByText('正在上传').length).toBeGreaterThan(0);
    expect(screen.getAllByText('42%').length).toBeGreaterThan(0);
    expect(
      screen.getByLabelText('素材账号素材A上传进度').getAttribute('value'),
    ).toBe('42');
  });
});
