import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
import { act } from 'react';
import { createRoot, type Root } from 'react-dom/client';
import { createDataset } from '@core/dataset';
import { useChartBuilderStore } from '../stores/ChartBuilderStore';
import { useDatasetStore } from '../stores/DatasetStore';
import { useSnippetStore } from '../stores/SnippetStore';
import { ChartBuilderModal } from './ChartBuilderModal';

// The builder preview embeds a real Vega chart in an effect; stub the renderer so
// this render test stays a pure React/DOM check (the loop we guard against happens
// during commit, long before any chart is drawn).
vi.mock('../services/chart-renderer', () => ({
  renderSpec: () => Promise.resolve({ destroy() {}, resize() {} }),
}));

// React 19 wants this flag set for act() to drive effects without warnings.
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;

const T = new Date('2026-06-01T00:00:00Z');
let container: HTMLDivElement;
let root: Root;

beforeEach(() => {
  useChartBuilderStore.getState().reset();
  useDatasetStore.getState().reset();
  useSnippetStore.getState().reset();
  container = document.createElement('div');
  document.body.appendChild(container);
  root = createRoot(container);
});

afterEach(() => {
  act(() => root.unmount());
  container.remove();
});

describe('ChartBuilderModal', () => {
  test('renders without an infinite update loop when the config has warnings (regression)', async () => {
    // Two numeric columns → default mark Point (clean). Switching to Bar makes it
    // "two measures on a non-scatter" → a NON-EMPTY warnings array — the exact
    // condition that previously looped because the warnings selector returned a
    // fresh array of objects on every render. The fix derives warnings via useMemo
    // over the stable `config` reference instead.
    const ds = createDataset({
      name: 'Nums',
      data: [
        { a: 1, b: 2 },
        { a: 3, b: 4 },
      ],
      format: 'json',
      source: 'inline',
      now: T,
    });
    useDatasetStore.getState().add(ds);
    useChartBuilderStore.getState().init(ds.id);
    useChartBuilderStore.getState().setMark('bar');
    expect(useChartBuilderStore.getState().config.mark).toBe('bar');

    // If the component looped, this act() would throw "Maximum update depth exceeded".
    await act(async () => {
      root.render(<ChartBuilderModal />);
      await Promise.resolve();
    });

    expect(container.textContent).toContain('Building from');
    expect(container.textContent).toContain('scatter'); // the guidance hint rendered
  });

  test('shows the empty state when no dataset is loaded', async () => {
    await act(async () => {
      root.render(<ChartBuilderModal />);
      await Promise.resolve();
    });
    expect(container.textContent).toContain('No dataset loaded');
  });
});
