import { beforeEach, describe, expect, it } from 'vitest';

import './components/TinyflowComponent.svelte';
import { Tinyflow } from './Tinyflow';

const waitForRender = () =>
  new Promise<void>((resolve) => {
    setTimeout(resolve, 0);
  });

describe('tinyflow store isolation', () => {
  beforeEach(() => {
    document.body.innerHTML = '';
  });

  it('keeps simultaneous canvas data isolated', async () => {
    const firstContainer = document.createElement('div');
    const secondContainer = document.createElement('div');
    document.body.append(firstContainer, secondContainer);

    const first = new Tinyflow({
      element: firstContainer,
      data: {
        nodes: [
          { id: 'first-source', position: { x: 0, y: 0 }, data: {} },
          { id: 'first-target', position: { x: 300, y: 0 }, data: {} },
        ],
        edges: [
          {
            id: 'first-edge',
            source: 'first-source',
            target: 'first-target',
          },
        ],
      },
    });
    const second = new Tinyflow({
      element: secondContainer,
      data: {
        nodes: [
          { id: 'second-source', position: { x: 0, y: 0 }, data: {} },
          { id: 'second-target', position: { x: 300, y: 0 }, data: {} },
        ],
        edges: [
          {
            id: 'second-edge',
            source: 'second-source',
            target: 'second-target',
          },
        ],
      },
    });

    await waitForRender();

    expect(first.getData()?.nodes.map((node) => node.id)).toEqual([
      'first-source',
      'first-target',
    ]);
    expect(second.getData()?.nodes.map((node) => node.id)).toEqual([
      'second-source',
      'second-target',
    ]);

    first.updateData({
      nodes: [
        { id: 'first-updated', position: { x: 100, y: 100 }, data: {} },
      ],
      edges: [],
    });
    await waitForRender();

    expect(first.getData()?.nodes.map((node) => node.id)).toEqual([
      'first-updated',
    ]);
    expect(first.getData()?.edges).toEqual([]);
    expect(second.getData()?.nodes.map((node) => node.id)).toEqual([
      'second-source',
      'second-target',
    ]);
    expect(second.getData()?.edges.map((edge) => edge.id)).toEqual([
      'second-edge',
    ]);

    first.destroy();
    second.destroy();
  });
});
