import { renderHook } from '@testing-library/react';
import { useLocking } from '../useLocking';
import { Node, Edge } from 'reactflow';

describe('useLocking', () => {
  const createMockNode = (id: string, locked = false): Node => ({
    id,
    type: 'element',
    position: { x: 0, y: 0 },
    data: { label: `Node ${id}`, locked },
  });

  const createMockEdge = (id: string, locked = false): Edge => ({
    id,
    source: 'node1',
    target: 'node2',
    data: { locked },
  });

  const defaultProps = {
    nodes: [] as Node[],
    edges: [] as Edge[],
    selectedNode: null as Node | null,
    selectedEdge: null as Edge | null,
  };

  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('isNodeLocked', () => {
    it('should return true for locked node', () => {
      const nodes = [createMockNode('node1', true)];
      const { result } = renderHook(() =>
        useLocking({ ...defaultProps, nodes })
      );

      expect(result.current.isNodeLocked('node1')).toBe(true);
    });

    it('should return false for unlocked node', () => {
      const nodes = [createMockNode('node1', false)];
      const { result } = renderHook(() =>
        useLocking({ ...defaultProps, nodes })
      );

      expect(result.current.isNodeLocked('node1')).toBe(false);
    });

    it('should return false for non-existent node', () => {
      const { result } = renderHook(() => useLocking(defaultProps));
      expect(result.current.isNodeLocked('nonexistent')).toBe(false);
    });
  });

  describe('isEdgeLocked', () => {
    it('should return true for locked edge', () => {
      const edges = [createMockEdge('edge1', true)];
      const { result } = renderHook(() =>
        useLocking({ ...defaultProps, edges })
      );

      expect(result.current.isEdgeLocked('edge1')).toBe(true);
    });

    it('should return false for unlocked edge', () => {
      const edges = [createMockEdge('edge1', false)];
      const { result } = renderHook(() =>
        useLocking({ ...defaultProps, edges })
      );

      expect(result.current.isEdgeLocked('edge1')).toBe(false);
    });

    it('should return false for non-existent edge', () => {
      const { result } = renderHook(() => useLocking(defaultProps));
      expect(result.current.isEdgeLocked('nonexistent')).toBe(false);
    });
  });

  describe('canDeleteSelected', () => {
    it('should return false when nothing is selected', () => {
      const { result } = renderHook(() => useLocking(defaultProps));
      expect(result.current.canDeleteSelected()).toBe(false);
    });

    it('should return true when unlocked node is selected', () => {
      const selectedNode = createMockNode('node1', false);
      const { result } = renderHook(() =>
        useLocking({ ...defaultProps, selectedNode })
      );

      expect(result.current.canDeleteSelected()).toBe(true);
    });

    it('should return false when locked node is selected', () => {
      const selectedNode = createMockNode('node1', true);
      const { result } = renderHook(() =>
        useLocking({ ...defaultProps, selectedNode })
      );

      expect(result.current.canDeleteSelected()).toBe(false);
    });

    it('should return true when unlocked edge is selected', () => {
      const selectedEdge = createMockEdge('edge1', false);
      const { result } = renderHook(() =>
        useLocking({ ...defaultProps, selectedEdge })
      );

      expect(result.current.canDeleteSelected()).toBe(true);
    });

    it('should return false when locked edge is selected', () => {
      const selectedEdge = createMockEdge('edge1', true);
      const { result } = renderHook(() =>
        useLocking({ ...defaultProps, selectedEdge })
      );

      expect(result.current.canDeleteSelected()).toBe(false);
    });

    it('should return true when unlocked node and unlocked edge are selected', () => {
      const selectedNode = createMockNode('node1', false);
      const selectedEdge = createMockEdge('edge1', false);
      const { result } = renderHook(() =>
        useLocking({ ...defaultProps, selectedNode, selectedEdge })
      );

      expect(result.current.canDeleteSelected()).toBe(true);
    });

    it('should return false when locked node and unlocked edge are selected', () => {
      const selectedNode = createMockNode('node1', true);
      const selectedEdge = createMockEdge('edge1', false);
      const { result } = renderHook(() =>
        useLocking({ ...defaultProps, selectedNode, selectedEdge })
      );

      expect(result.current.canDeleteSelected()).toBe(false);
    });
  });

  describe('return value structure', () => {
    it('should return all expected properties', () => {
      const { result } = renderHook(() => useLocking(defaultProps));

      expect(typeof result.current.isNodeLocked).toBe('function');
      expect(typeof result.current.isEdgeLocked).toBe('function');
      expect(typeof result.current.canDeleteSelected).toBe('function');
    });
  });
});
