/* @vitest-environment jsdom */

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

import type {
  CanvasGenerationDialogState,
  CanvasLayer,
} from './ImageCanvasEditorTypes';
import { ImageCanvasWorldView } from './ImageCanvasWorldView';

function createLayer(overrides: Partial<CanvasLayer> = {}): CanvasLayer {
  return {
    id: 'layer-1',
    resourceId: 'resource-1',
    title: '角色主图',
    src: 'data:image/png;base64,layer',
    x: 120,
    y: 160,
    width: 320,
    height: 240,
    originalWidth: 640,
    originalHeight: 480,
    zIndex: 1,
    sourceType: 'uploaded',
    ...overrides,
  };
}

function createGenerationDialog(
  overrides: Partial<CanvasGenerationDialogState> = {},
): CanvasGenerationDialogState {
  return {
    id: 'dialog-1',
    mode: 'generate',
    prompt: '生成一张图',
    status: 'idle',
    placeholder: {
      x: 480,
      y: 320,
      width: 360,
      height: 240,
      originalWidth: 1024,
      originalHeight: 768,
    },
    ...overrides,
  };
}

function renderWorldView(
  overrides: Partial<Parameters<typeof ImageCanvasWorldView>[0]> = {},
) {
  const props: Parameters<typeof ImageCanvasWorldView>[0] = {
    viewport: { x: 10, y: 20, scale: 1.5 },
    snapGuide: null,
    layers: [createLayer()],
    selectedLayerIds: [],
    hoveredLayerId: null,
    canvasMarquee: null,
    canvasGenerationDialogs: [],
    generateDialog: null,
    quickEditPanel: null,
    generationComposerStyle: null,
    onLayerPointerDown: vi.fn(),
    onLayerClick: vi.fn(),
    onLayerContextMenu: vi.fn(),
    onLayerMouseEnter: vi.fn(),
    onLayerMouseLeave: vi.fn(),
    onOpenLayerMetadata: vi.fn(),
    onGenerationFramePointerDown: vi.fn(),
    onActivateGenerationDialog: vi.fn(),
    ...overrides,
  };

  const result = render(<ImageCanvasWorldView {...props} />);

  return { props, ...result };
}

describe('ImageCanvasWorldView', () => {
  it('renders visible layers and filters hidden layers', () => {
    const visibleLayer = createLayer({ title: '可见图层', zIndex: 2 });
    const hiddenLayer = createLayer({
      id: 'layer-hidden',
      resourceId: 'resource-hidden',
      title: '隐藏图层',
      hidden: true,
    });

    renderWorldView({
      layers: [hiddenLayer, visibleLayer],
      selectedLayerIds: [visibleLayer.id],
      hoveredLayerId: visibleLayer.id,
      quickEditPanel: {
        sourceLayerId: visibleLayer.id,
        prompt: '快速编辑',
        size: '1024x1024',
        model: 'gpt-image-2',
        status: 'generating',
      },
    });

    const visibleButton = screen.getByRole('button', { name: '选择可见图层' });

    expect(screen.queryByRole('button', { name: '选择隐藏图层' })).toBeNull();
    expect(visibleButton.className).toContain(
      'image-canvas-editor__layer--selected',
    );
    expect(visibleButton.className).toContain(
      'image-canvas-editor__layer--hovered',
    );
    expect(visibleButton.className).toContain(
      'image-canvas-editor__layer--generating',
    );
    expect(visibleButton.style.left).toBe('120px');
    expect(visibleButton.style.top).toBe('160px');
    expect(screen.getByText('640 x 480 px')).toBeTruthy();
    expect(screen.getByRole('status', { name: '' }).textContent).toBe('生成中');
  });

  it('forwards layer pointer, hover, context menu and metadata actions', () => {
    const layer = createLayer({ assetKind: 'character' });
    const { props } = renderWorldView({ layers: [layer] });

    const layerButton = screen.getByRole('button', { name: '选择角色主图' });
    const metadataButton = within(layerButton).getByRole('button', {
      name: '查看角色主图图片信息',
    });

    fireEvent.pointerDown(layerButton);
    fireEvent.click(layerButton);
    fireEvent.contextMenu(layerButton);
    fireEvent.mouseEnter(layerButton);
    fireEvent.mouseLeave(layerButton);
    fireEvent.click(metadataButton);

    expect(props.onLayerPointerDown).toHaveBeenCalledWith(
      expect.any(Object),
      layer,
    );
    expect(props.onLayerClick).toHaveBeenCalledWith(expect.any(Object), layer);
    expect(props.onLayerContextMenu).toHaveBeenCalledWith(
      expect.any(Object),
      layer,
    );
    expect(props.onLayerMouseEnter).toHaveBeenCalledWith(layer.id);
    expect(props.onLayerMouseLeave).toHaveBeenCalledWith(layer.id);
    expect(props.onOpenLayerMetadata).toHaveBeenCalledWith(layer);
    expect(screen.getByText('角色')).toBeTruthy();
  });

  it('renders snap guides, marquee and floating generation status', () => {
    renderWorldView({
      snapGuide: { vertical: 288, horizontal: 344 },
      canvasMarquee: {
        pointerId: 1,
        startX: 40,
        startY: 50,
        currentX: 190,
        currentY: 230,
      },
      generateDialog: {
        id: 'dialog-active',
        mode: 'generate',
        prompt: '生成中',
        status: 'generating',
      },
      generationComposerStyle: { left: 12, top: 24 },
    });

    expect(
      screen.getByTestId('image-canvas-editor-snap-guide-vertical').style.left,
    ).toBe('288px');
    expect(
      screen.getByTestId('image-canvas-editor-snap-guide-horizontal').style.top,
    ).toBe('344px');
    expect(screen.getByText('生成中')).toBeTruthy();

    const world = document.querySelector('.image-canvas-editor__world');
    const marquee = world?.querySelector('.image-canvas-editor__canvas-marquee');

    expect(world?.getAttribute('style')).toContain(
      'transform: translate(10px, 20px) scale(1.5)',
    );
    expect((marquee as HTMLElement | null)?.style.width).toBe('100px');
    expect((marquee as HTMLElement | null)?.style.height).toBe('120px');
  });

  it('renders generation placeholders and forwards frame actions', () => {
    const dialog = createGenerationDialog({
      mode: 'icon',
      status: 'generating',
    });
    const { props } = renderWorldView({
      canvasGenerationDialogs: [
        dialog,
        createGenerationDialog({
          id: 'dialog-without-placeholder',
          placeholder: undefined,
        }),
      ],
    });

    const frame = screen.getByRole('button', { name: '图标素材生成占位图' });

    expect(within(frame).getByText('Icon Generator')).toBeTruthy();
    expect(within(frame).getByText('图标')).toBeTruthy();
    expect(within(frame).getByText('1024 x 768')).toBeTruthy();
    expect(within(frame).getByRole('status').textContent).toBe('生成中');

    fireEvent.pointerDown(frame);
    fireEvent.doubleClick(frame);

    expect(props.onGenerationFramePointerDown).toHaveBeenCalledWith(
      expect.any(Object),
      dialog,
    );
    expect(props.onActivateGenerationDialog).toHaveBeenCalledWith(dialog);
    expect(screen.queryByText('dialog-without-placeholder')).toBeNull();
  });

  it('keeps saved generator placeholders hidden after a result layer exists', () => {
    renderWorldView({
      layers: [createLayer({ id: 'layer-generated', title: '生成图片' })],
      canvasGenerationDialogs: [
        createGenerationDialog({
          generatedLayerId: 'layer-generated',
          placeholder: {
            x: 80,
            y: 90,
            width: 420,
            height: 420,
            originalWidth: 2048,
            originalHeight: 2048,
          },
        }),
      ],
    });

    expect(screen.getByRole('button', { name: '选择生成图片' })).toBeTruthy();
    expect(
      screen.queryByRole('button', { name: '图像生成占位图' }),
    ).toBeNull();
  });
});
