/**
 * WidgetGrid Component Tests
 * Following TDD - write tests first!
 */

import { describe, it, expect, vi, beforeAll } from "vitest";
import { render, screen } from "@testing-library/react";
import { WidgetGrid } from "../WidgetGrid";
import type { WidgetPlacement } from "@mosaic/shared";

// ResizeObserver is not available in jsdom
beforeAll((): void => {
  global.ResizeObserver = vi.fn().mockImplementation(() => ({
    observe: vi.fn(),
    unobserve: vi.fn(),
    disconnect: vi.fn(),
  }));
});

// Mock react-grid-layout
vi.mock("react-grid-layout", () => ({
  default: ({ children }: { children: React.ReactNode }): React.JSX.Element => (
    <div data-testid="grid-layout">{children}</div>
  ),
  Responsive: ({ children }: { children: React.ReactNode }): React.JSX.Element => (
    <div data-testid="responsive-grid-layout">{children}</div>
  ),
}));

describe("WidgetGrid", (): void => {
  const mockLayout: WidgetPlacement[] = [
    { i: "tasks-1", x: 0, y: 0, w: 2, h: 2 },
    { i: "calendar-1", x: 2, y: 0, w: 2, h: 2 },
  ];

  const mockOnLayoutChange = vi.fn();

  it("should render grid layout", (): void => {
    render(<WidgetGrid layout={mockLayout} onLayoutChange={mockOnLayoutChange} />);

    expect(screen.getByTestId("grid-layout")).toBeInTheDocument();
  });

  it("should render widgets from layout", (): void => {
    render(<WidgetGrid layout={mockLayout} onLayoutChange={mockOnLayoutChange} />);

    // Should render correct number of widgets
    const widgets = screen.getAllByTestId(/widget-/);
    expect(widgets).toHaveLength(mockLayout.length);
  });

  it("should call onLayoutChange when layout changes", (): void => {
    const { rerender } = render(
      <WidgetGrid layout={mockLayout} onLayoutChange={mockOnLayoutChange} />
    );

    const newLayout: WidgetPlacement[] = [
      { i: "tasks-1", x: 1, y: 0, w: 2, h: 2 },
      { i: "calendar-1", x: 2, y: 0, w: 2, h: 2 },
    ];

    rerender(<WidgetGrid layout={newLayout} onLayoutChange={mockOnLayoutChange} />);

    // Layout change handler should be set up (actual calls handled by react-grid-layout)
    expect(mockOnLayoutChange).toBeDefined();
  });

  it("should support edit mode", (): void => {
    render(<WidgetGrid layout={mockLayout} onLayoutChange={mockOnLayoutChange} isEditing={true} />);

    // In edit mode, widgets should have edit controls
    expect(screen.getByTestId("grid-layout")).toBeInTheDocument();
  });

  it("should support read-only mode", (): void => {
    render(
      <WidgetGrid layout={mockLayout} onLayoutChange={mockOnLayoutChange} isEditing={false} />
    );

    expect(screen.getByTestId("grid-layout")).toBeInTheDocument();
  });

  it("should render empty state when no widgets", (): void => {
    render(<WidgetGrid layout={[]} onLayoutChange={mockOnLayoutChange} />);

    expect(screen.getByText(/no widgets/i)).toBeInTheDocument();
  });

  it("should handle widget removal", (): void => {
    const mockOnRemoveWidget = vi.fn();
    render(
      <WidgetGrid
        layout={mockLayout}
        onLayoutChange={mockOnLayoutChange}
        onRemoveWidget={mockOnRemoveWidget}
        isEditing={true}
      />
    );

    // Widget removal should be supported
    expect(mockOnRemoveWidget).toBeDefined();
  });

  it("should apply custom className", (): void => {
    const { container } = render(
      <WidgetGrid layout={mockLayout} onLayoutChange={mockOnLayoutChange} className="custom-grid" />
    );

    expect(container.querySelector(".custom-grid")).toBeInTheDocument();
  });
});
