import {act} from '@testing-library/react';
import useFlowStore from '../../../../src/pages/VisProgPage/visualProgrammingUI/VisProgStores.tsx';
import { mockReactFlow } from '../../../setupFlowTests.ts';

beforeAll(() => {
  mockReactFlow();
});

describe('FlowStore Functionality', () => {
  describe('Node changes', () => {
    // currently just using a single function from the ReactFlow library,
    // so testing would mean we are testing already tested behavior.
    // if implementation gets modified tests should be added for custom behavior
  });
  describe('Edge changes', () => {
    // currently just using a single function from the ReactFlow library,
    // so testing would mean we are testing already tested behavior.
    // if implementation gets modified tests should be added for custom behavior
  })
  describe('ReactFlow onConnect', () => {
    test('adds an edge when onConnect is triggered', () => {
      const {onConnect} = useFlowStore.getState();

      act(() => {
        onConnect({
          source: 'A',
          target: 'B',
          sourceHandle: null,
          targetHandle: null,
        });
      });

      const updatedEdges = useFlowStore.getState().edges;
      expect(updatedEdges).toHaveLength(1);
      expect(updatedEdges[0]).toMatchObject({
        source: 'A',
        target: 'B',
      });
    });
  });
  describe('ReactFlow onReconnect', () => {
    test('reconnects an existing edge when onReconnect is triggered', () => {
      const {onReconnect} = useFlowStore.getState();
      const oldEdge = {
        id: 'xy-edge__A-B',
        source: 'A',
        target: 'B'
      };
      const newConnection = {
        source: 'A',
        target: 'C',
        sourceHandle: null,
        targetHandle: null,
      };
      act(() => {
        useFlowStore.setState({
          edges: [oldEdge]
        });
        onReconnect(oldEdge, newConnection);
      });

      const updatedEdges = useFlowStore.getState().edges;
      expect(updatedEdges).toHaveLength(1);
      expect(updatedEdges[0]).toMatchObject({
        id: 'xy-edge__A-C',
        source: 'A',
        target: 'C',
      });
    });
  });
  describe('ReactFlow onReconnectStart', () => {
    test('does correct setup for edge reconnection sequences', () => {
      const {onReconnectStart} = useFlowStore.getState();

      act(() => {
        onReconnectStart();
      });

      const updatedState = useFlowStore.getState().edgeReconnectSuccessful;
      expect(updatedState).toEqual(false);
    });
  });
  describe('ReactFlow onReconnectEnd', () => {
  });
  describe('ReactFlow setNodes', () => {
    test('sets nodes to the provided list of nodes', () => {
      const {setNodes} = useFlowStore.getState();

      act(() => {
        setNodes([
          {
            id: 'start',
            type: 'start',
            position: {x: 0, y: 0},
            data: {label: 'start'}
          },
          {
            id: 'end',
            type: 'end',
            position: {x: 0, y: 300},
            data: {label: 'End'}
          }
        ]);
      });

      const updatedNodes = useFlowStore.getState().nodes;
      expect(updatedNodes).toHaveLength(2);
      expect(updatedNodes[0]).toMatchObject({
        id: 'start',
        type: 'start',
        position: {x: 0, y: 0},
        data: {label: 'start'}
      });
      expect(updatedNodes[1]).toMatchObject({
        id: 'end',
        type: 'end',
        position: {x: 0, y: 300},
        data: {label: 'End'}
      });
    });
  });
  describe('ReactFlow setEdges', () => {
   test('sets edges to the provided list of edges', () => {
      const {setEdges} = useFlowStore.getState();

      act(() => {
        setEdges([
          {
            id: 'start-end',
            source: 'start',
            target: 'end'
          }
        ]);
      });

      const updatedEdges = useFlowStore.getState().edges;
      expect(updatedEdges).toHaveLength(1);
      expect(updatedEdges[0]).toMatchObject({
        id: 'start-end',
        source: 'start',
        target: 'end'
      });
    });
  });
});
