import { renderHook, act } from '@testing-library/react';
import { useCloseHandler } from '../useCloseHandler';

// Mock store
let mockModelData: any = null;

jest.mock('../../store/store', () => ({
  useStore: jest.fn((selector) => {
    const state = {
      modelData: mockModelData,
    };
    return selector(state);
  }),
}));

describe('useCloseHandler', () => {
  let mockShowConfirmationDialog: jest.Mock;
  let mockWrapper: HTMLDivElement;
  let originalLocation: Location;

  beforeEach(() => {
    jest.clearAllMocks();
    mockShowConfirmationDialog = jest.fn();
    mockModelData = {
      metadata: { label: 'Test Workflow' },
    };

    // Create mock wrapper element
    mockWrapper = document.createElement('div');
    mockWrapper.id = 'workflow-modeler-wrapper';
    document.body.appendChild(mockWrapper);

    // Mock window.location
    originalLocation = window.location;
    Object.defineProperty(window, 'location', {
      value: { href: '' },
      writable: true,
      configurable: true,
    });
  });

  afterEach(() => {
    // Clean up DOM
    const wrapper = document.getElementById('workflow-modeler-wrapper');
    if (wrapper) wrapper.remove();

    const restoreBar = document.getElementById('workflow-modeler-restore-bar');
    if (restoreBar) restoreBar.remove();

    Object.defineProperty(window, 'location', {
      value: originalLocation,
      writable: true,
      configurable: true,
    });
  });

  const renderUseCloseHandler = (props = {}) => {
    return renderHook(() =>
      useCloseHandler({
        settings: {},
        hasUnsavedChanges: false,
        showConfirmationDialog: mockShowConfirmationDialog,
        ...props,
      })
    );
  };

  describe('return values', () => {
    it('should return all required handlers and refs', () => {
      const { result } = renderUseCloseHandler();

      expect(typeof result.current.handleClose).toBe('function');
      expect(typeof result.current.handleMinimize).toBe('function');
      expect(typeof result.current.handleSaveComplete).toBe('function');
      expect(result.current.saveButtonRef).toBeDefined();
    });
  });

  describe('handleClose', () => {
    it('should close immediately when no unsaved changes', () => {
      const { result } = renderUseCloseHandler({
        settings: { modeler: { stayInContextOnClose: true } },
        hasUnsavedChanges: false,
      });

      act(() => {
        result.current.handleClose();
      });

      expect(mockShowConfirmationDialog).not.toHaveBeenCalled();
      expect(mockWrapper.style.display).toBe('none');
    });

    it('should show confirmation dialog when has unsaved changes', () => {
      const { result } = renderUseCloseHandler({
        hasUnsavedChanges: true,
      });

      act(() => {
        result.current.handleClose();
      });

      expect(mockShowConfirmationDialog).toHaveBeenCalledWith(
        'Unsaved Changes',
        'You have unsaved changes. What would you like to do?',
        'warning',
        expect.any(Function),
        expect.any(Function)
      );
    });

    it('should navigate to collection URL when stayInContextOnClose is false', () => {
      const { result } = renderUseCloseHandler({
        settings: {
          modeler: { stayInContextOnClose: false },
          modeler_api: { collection_url: '/workflows' },
        },
        hasUnsavedChanges: false,
      });

      act(() => {
        result.current.handleClose();
      });

      expect(window.location.href).toBe('/workflows');
    });

    it('should hide wrapper when stayInContextOnClose is true', () => {
      const { result } = renderUseCloseHandler({
        settings: { modeler: { stayInContextOnClose: true } },
        hasUnsavedChanges: false,
      });

      act(() => {
        result.current.handleClose();
      });

      expect(mockWrapper.style.display).toBe('none');
    });
  });

  describe('handleMinimize', () => {
    it('should hide the wrapper element', () => {
      const { result } = renderUseCloseHandler();

      act(() => {
        result.current.handleMinimize();
      });

      expect(mockWrapper.style.display).toBe('none');
    });

    it('should create restore bar element', () => {
      const { result } = renderUseCloseHandler();

      act(() => {
        result.current.handleMinimize();
      });

      const restoreBar = document.getElementById('workflow-modeler-restore-bar');
      expect(restoreBar).toBeDefined();
      expect(restoreBar?.className).toBe('workflow-restore-bar');
    });

    it('should include model name in restore bar', () => {
      mockModelData = { metadata: { label: 'My Workflow' } };
      const { result } = renderUseCloseHandler();

      act(() => {
        result.current.handleMinimize();
      });

      const restoreBar = document.getElementById('workflow-modeler-restore-bar');
      expect(restoreBar?.innerHTML).toContain('My Workflow');
    });

    it('should use default name when model has no label', () => {
      mockModelData = { metadata: {} };
      const { result } = renderUseCloseHandler();

      act(() => {
        result.current.handleMinimize();
      });

      const restoreBar = document.getElementById('workflow-modeler-restore-bar');
      expect(restoreBar?.innerHTML).toContain('Workflow Modeler');
    });

    it('should replace existing restore bar', () => {
      // Create an existing restore bar
      const existingBar = document.createElement('div');
      existingBar.id = 'workflow-modeler-restore-bar';
      existingBar.innerHTML = 'Old content';
      document.body.appendChild(existingBar);

      const { result } = renderUseCloseHandler();

      act(() => {
        result.current.handleMinimize();
      });

      const restoreBars = document.querySelectorAll('#workflow-modeler-restore-bar');
      expect(restoreBars.length).toBe(1);
      expect(restoreBars[0].innerHTML).not.toContain('Old content');
    });
  });

  describe('restore functionality', () => {
    it('should restore wrapper when restore button is clicked', () => {
      const { result } = renderUseCloseHandler();

      act(() => {
        result.current.handleMinimize();
      });

      expect(mockWrapper.style.display).toBe('none');

      // Find and click restore button
      const restoreBtn = document.querySelector('.restore-btn') as HTMLButtonElement;
      expect(restoreBtn).toBeDefined();

      act(() => {
        restoreBtn.click();
      });

      expect(mockWrapper.style.display).toBe('');
    });

    it('should remove restore bar when restored', () => {
      const { result } = renderUseCloseHandler();

      act(() => {
        result.current.handleMinimize();
      });

      const restoreBtn = document.querySelector('.restore-btn') as HTMLButtonElement;

      act(() => {
        restoreBtn.click();
      });

      const restoreBar = document.getElementById('workflow-modeler-restore-bar');
      expect(restoreBar).toBeNull();
    });
  });

  describe('handleSaveComplete', () => {
    it('should call setHasUnsavedChanges with false', () => {
      const { result } = renderUseCloseHandler();
      const mockSetHasUnsavedChanges = jest.fn();

      act(() => {
        result.current.handleSaveComplete(mockSetHasUnsavedChanges);
      });

      expect(mockSetHasUnsavedChanges).toHaveBeenCalledWith(false);
    });

    it('should close after save when pending close flag is set', () => {
      const { result } = renderUseCloseHandler({
        settings: { modeler: { stayInContextOnClose: true } },
        hasUnsavedChanges: true,
      });

      // Trigger confirmation dialog
      act(() => {
        result.current.handleClose();
      });

      // Call the save and close callback (first callback)
      const saveAndCloseCallback = mockShowConfirmationDialog.mock.calls[0][3];

      // Mock the save button click
      const mockButton = document.createElement('button');
      (result.current.saveButtonRef as any).current = mockButton;

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

      // Simulate save complete
      const mockSetHasUnsavedChanges = jest.fn();
      act(() => {
        result.current.handleSaveComplete(mockSetHasUnsavedChanges);
      });

      expect(mockWrapper.style.display).toBe('none');
    });

    it('should not close after save when no pending close', () => {
      const { result } = renderUseCloseHandler({
        settings: { modeler: { stayInContextOnClose: true } },
      });

      const mockSetHasUnsavedChanges = jest.fn();

      act(() => {
        result.current.handleSaveComplete(mockSetHasUnsavedChanges);
      });

      // Wrapper should still be visible
      expect(mockWrapper.style.display).toBe('');
    });
  });

  describe('cleanup', () => {
    it('should remove restore bar on unmount', () => {
      const { result, unmount } = renderUseCloseHandler();

      act(() => {
        result.current.handleMinimize();
      });

      expect(document.getElementById('workflow-modeler-restore-bar')).toBeDefined();

      unmount();

      expect(document.getElementById('workflow-modeler-restore-bar')).toBeNull();
    });
  });

  describe('confirmation dialog callbacks', () => {
    it('should provide save and close callback', () => {
      const { result } = renderUseCloseHandler({
        hasUnsavedChanges: true,
      });

      act(() => {
        result.current.handleClose();
      });

      const saveAndCloseCallback = mockShowConfirmationDialog.mock.calls[0][3];
      expect(typeof saveAndCloseCallback).toBe('function');
    });

    it('should provide close without save callback', () => {
      const { result } = renderUseCloseHandler({
        hasUnsavedChanges: true,
        settings: { modeler: { stayInContextOnClose: true } },
      });

      act(() => {
        result.current.handleClose();
      });

      const closeWithoutSaveCallback = mockShowConfirmationDialog.mock.calls[0][4];
      expect(typeof closeWithoutSaveCallback).toBe('function');

      // Execute the callback
      act(() => {
        closeWithoutSaveCallback();
      });

      expect(mockWrapper.style.display).toBe('none');
    });
  });

  describe('edge cases', () => {
    it('should handle missing wrapper element gracefully', () => {
      // Remove wrapper
      mockWrapper.remove();

      const { result } = renderUseCloseHandler({
        settings: { modeler: { stayInContextOnClose: true } },
        hasUnsavedChanges: false,
      });

      expect(() => {
        act(() => {
          result.current.handleClose();
        });
      }).not.toThrow();
    });

    it('should handle missing collection URL', () => {
      const { result } = renderUseCloseHandler({
        settings: { modeler: { stayInContextOnClose: false } },
        hasUnsavedChanges: false,
      });

      expect(() => {
        act(() => {
          result.current.handleClose();
        });
      }).not.toThrow();
    });
  });
});
