import {
  getSelection,
  getFirstRange,
  isActiveElement,
  clearRange,
  setRange,
} from '../selection';

describe('selection', () => {
  beforeEach(() => {
    // Clear any existing selections
    window.getSelection()?.removeAllRanges();
  });

  describe('getSelection', () => {
    it('should return window selection object', () => {
      const selection = getSelection();
      expect(selection).toBeDefined();
      expect(selection).toBe(window.getSelection());
    });
  });

  describe('isActiveElement', () => {
    it('should return true when element is active', () => {
      const element = document.createElement('input');
      document.body.appendChild(element);
      element.focus();

      expect(isActiveElement(element)).toBe(true);

      document.body.removeChild(element);
    });

    it('should return false when element is not active', () => {
      const element = document.createElement('div');
      document.body.appendChild(element);

      expect(isActiveElement(element)).toBe(false);

      document.body.removeChild(element);
    });

    it('should return false for null element', () => {
      // isActiveElement returns null when element is null, not false
      expect(isActiveElement(null)).toBeFalsy();
    });
  });

  describe('clearRange', () => {
    it('should clear all ranges from selection', () => {
      const element = document.createElement('div');
      element.textContent = 'Test content';
      document.body.appendChild(element);

      // Create a selection
      const range = document.createRange();
      range.selectNodeContents(element);
      window.getSelection()?.addRange(range);

      expect(window.getSelection()?.rangeCount).toBeGreaterThan(0);

      clearRange();

      expect(window.getSelection()?.rangeCount).toBe(0);

      document.body.removeChild(element);
    });
  });

  describe('getFirstRange', () => {
    it('should return null when no selection exists', () => {
      const element = document.createElement('div');
      document.body.appendChild(element);

      const result = getFirstRange(element);
      expect(result).toBeNull();

      document.body.removeChild(element);
    });

    it('should return range info when selection exists within element', () => {
      const element = document.createElement('div');
      element.textContent = 'Test content';
      document.body.appendChild(element);

      const range = document.createRange();
      const textNode = element.firstChild;
      if (textNode) {
        range.setStart(textNode, 0);
        range.setEnd(textNode, 4);
        window.getSelection()?.addRange(range);

        const result = getFirstRange(element);
        expect(result).toBeDefined();
        expect(result?.startOffset).toBe(0);
        expect(result?.endOffset).toBe(4);
      }

      document.body.removeChild(element);
    });

    it('should return null when selection is outside element', () => {
      const element1 = document.createElement('div');
      element1.textContent = 'Test content 1';
      const element2 = document.createElement('div');
      element2.textContent = 'Test content 2';
      document.body.appendChild(element1);
      document.body.appendChild(element2);

      const range = document.createRange();
      const textNode = element2.firstChild;
      if (textNode) {
        range.setStart(textNode, 0);
        range.setEnd(textNode, 4);
        window.getSelection()?.addRange(range);

        const result = getFirstRange(element1);
        expect(result).toBeNull();
      }

      document.body.removeChild(element1);
      document.body.removeChild(element2);
    });
  });

  describe('setRange', () => {
    let originalConsoleError: typeof console.error;

    beforeEach(() => {
      // Suppress console.error for DOMException in test environment
      originalConsoleError = console.error;
      console.error = jest.fn();
    });

    afterEach(() => {
      // Restore original console.error
      console.error = originalConsoleError;
    });

    it('should set range on element with text node', () => {
      const element = document.createElement('div');
      element.textContent = 'Test content';
      document.body.appendChild(element);

      // Note: setRange may fail in test environment, so we just verify it doesn't throw
      expect(() => {
        setRange(element, 0, 4);
      }).not.toThrow();

      document.body.removeChild(element);
    });

    it('should handle element with no children', () => {
      const element = document.createElement('div');
      document.body.appendChild(element);

      expect(() => {
        setRange(element, 0, 0);
      }).not.toThrow();

      document.body.removeChild(element);
    });

    it('should handle element with multiple children', () => {
      const element = document.createElement('div');
      element.innerHTML = '<span>Hello</span><span>World</span>';
      document.body.appendChild(element);

      expect(() => {
        setRange(element, 0, 5);
      }).not.toThrow();

      document.body.removeChild(element);
    });
  });
});

