/* @vitest-environment jsdom */

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

import type { StageMinimapModel } from './ImageCanvasInteractionModel';
import { ImageCanvasPanelDockView } from './ImageCanvasPanelDockView';

function renderPanelDock(
  overrides: Partial<Parameters<typeof ImageCanvasPanelDockView>[0]> = {},
) {
  const props: Parameters<typeof ImageCanvasPanelDockView>[0] = {
    viewport: { x: 0, y: 0, scale: 1 },
    canvasBackgroundColor: '#f8fafc',
    canvasBackgroundHexValue: '#f8fafc',
    canUndo: true,
    canRedo: false,
    isZoomMenuOpen: false,
    isBackgroundSettingsOpen: false,
    activeSidebarPanel: null,
    isMinimapOpen: false,
    minimapModel: null,
    onFitLayers: vi.fn(),
    onUndoCanvasChange: vi.fn(),
    onRedoCanvasChange: vi.fn(),
    onUpdateScaleFromCenter: vi.fn(),
    onToggleZoomMenu: vi.fn(),
    onCloseZoomMenu: vi.fn(),
    onToggleBackgroundSettings: vi.fn(),
    onApplyCanvasBackgroundColor: vi.fn(),
    onCanvasBackgroundHexChange: vi.fn(),
    onToggleSidebarPanel: vi.fn(),
    onToggleMinimap: vi.fn(),
    onMinimapPointerDown: vi.fn(),
    ...overrides,
  };

  render(<ImageCanvasPanelDockView {...props} />);

  return props;
}

describe('ImageCanvasPanelDockView', () => {
  it('renders panel dock actions and forwards common controls', () => {
    const props = renderPanelDock({
      activeSidebarPanel: 'assets',
      isMinimapOpen: true,
      minimapModel: {
        bounds: { minX: 0, minY: 0, maxX: 100, maxY: 100 },
        scale: 1,
        layers: [],
        viewport: { left: '10%', top: '12%', width: '20%', height: '24%' },
      } satisfies StageMinimapModel,
    });

    const toolbar = screen.getByRole('toolbar', { name: '画布面板入口' });

    expect(
      within(toolbar).getByRole('button', { name: '打开素材' }).getAttribute(
        'aria-pressed',
      ),
    ).toBe('true');
    expect(
      (
        within(toolbar).getByRole('button', { name: '重做' }) as HTMLButtonElement
      ).disabled,
    ).toBe(true);
    expect(screen.getByRole('button', { name: '画布小地图' })).toBeTruthy();

    fireEvent.click(screen.getByRole('button', { name: '重置画布视图' }));
    fireEvent.click(within(toolbar).getByRole('button', { name: '撤销' }));
    fireEvent.click(within(toolbar).getByRole('button', { name: '打开图层' }));
    fireEvent.click(within(toolbar).getByRole('button', { name: '切换小地图' }));

    expect(props.onFitLayers).toHaveBeenCalledTimes(1);
    expect(props.onUndoCanvasChange).toHaveBeenCalledTimes(1);
    expect(props.onToggleSidebarPanel).toHaveBeenCalledWith('layers');
    expect(props.onToggleMinimap).toHaveBeenCalledTimes(1);
  });

  it('renders zoom and background settings with callback wiring', () => {
    const props = renderPanelDock({
      isZoomMenuOpen: true,
      isBackgroundSettingsOpen: true,
    });

    fireEvent.click(screen.getByRole('menuitem', { name: '缩放至50%' }));
    fireEvent.click(screen.getByRole('menuitem', { name: '显示画布所有元素' }));

    expect(props.onUpdateScaleFromCenter).toHaveBeenCalledWith(0.5);
    expect(props.onFitLayers).toHaveBeenCalledTimes(1);
    expect(props.onCloseZoomMenu).toHaveBeenCalledTimes(2);

    const panel = screen.getByRole('dialog', { name: '画布背景设置' });

    fireEvent.click(within(panel).getByRole('button', { name: '暖灰' }));
    fireEvent.change(within(panel).getByLabelText('自定义画布背景色'), {
      target: { value: '#ffffff' },
    });
    fireEvent.change(within(panel).getByLabelText('画布背景十六进制颜色'), {
      target: { value: '#abc' },
    });
    fireEvent.click(within(panel).getByRole('button', { name: '恢复默认' }));
    fireEvent.click(within(panel).getByRole('button', { name: '关闭画布背景设置' }));

    expect(props.onApplyCanvasBackgroundColor).toHaveBeenCalledWith('#f3f0ea');
    expect(props.onApplyCanvasBackgroundColor).toHaveBeenCalledWith('#ffffff');
    expect(props.onCanvasBackgroundHexChange).toHaveBeenCalledWith('#abc');
    expect(props.onApplyCanvasBackgroundColor).toHaveBeenCalledWith('#f8fafc');
    expect(props.onToggleBackgroundSettings).toHaveBeenCalledTimes(1);
  });
});
