import { describe, test, expect, beforeEach, vi } from 'vitest';
import type { Page } from 'playwright';

describe('Wizard Dismissal Detection', () => {
  let mockPage: Page;

  beforeEach(() => {
    mockPage = {
      locator: vi.fn(),
      waitForTimeout: vi.fn().mockResolvedValue(undefined),
    } as unknown as Page;
  });

  describe('isWizardModalDismissed', () => {
    test('should return FALSE when modal is transitioning between steps (temporarily hidden)', async () => {
      const modalSelector = '.modal.fade.in';
      
      // Simulate step transition: modal not visible initially, then reappears after 500ms
      let checkCount = 0;
      const mockLocator = {
        isVisible: vi.fn().mockImplementation(() => {
          checkCount++;
          // First check: modal not visible (transitioning)
          if (checkCount === 1) return Promise.resolve(false);
          // Second check after 500ms delay: modal reappears (transition complete)
          if (checkCount === 2) return Promise.resolve(true);
          return Promise.resolve(false);
        }),
      };
      
      vi.mocked(mockPage.locator).mockReturnValue(mockLocator as unknown as ReturnType<Page['locator']>);

      // Simulate the isWizardModalDismissed logic
      const isWizardModalDismissed = async (): Promise<boolean> => {
        const modalVisible = await mockPage.locator(modalSelector).isVisible().catch(() => false);
        
        if (modalVisible) {
          return false;
        }
        
        // Wait 500ms to distinguish between transition and dismissal
        await mockPage.waitForTimeout(500);
        
        // Check again after delay
        const stillNotVisible = !await mockPage.locator(modalSelector).isVisible().catch(() => false);
        
        return stillNotVisible;
      };

      const result = await isWizardModalDismissed();

      // Should be FALSE because modal reappeared after transition
      expect(result).toBe(false);
      expect(mockPage.waitForTimeout).toHaveBeenCalledWith(500);
      expect(mockLocator.isVisible).toHaveBeenCalledTimes(2);
    });

    test('should return TRUE when modal is permanently dismissed by user', async () => {
      const modalSelector = '.modal.fade.in';
      
      // Simulate user dismissal: modal not visible and stays not visible
      const mockLocator = {
        isVisible: vi.fn().mockResolvedValue(false),
      };
      
      vi.mocked(mockPage.locator).mockReturnValue(mockLocator as unknown as ReturnType<Page['locator']>);

      const isWizardModalDismissed = async (): Promise<boolean> => {
        const modalVisible = await mockPage.locator(modalSelector).isVisible().catch(() => false);
        
        if (modalVisible) {
          return false;
        }
        
        await mockPage.waitForTimeout(500);
        
        const stillNotVisible = !await mockPage.locator(modalSelector).isVisible().catch(() => false);
        
        return stillNotVisible;
      };

      const result = await isWizardModalDismissed();

      expect(result).toBe(true);
      expect(mockLocator.isVisible).toHaveBeenCalledTimes(2);
    });

    test('should return FALSE when modal is visible (user did not dismiss)', async () => {
      const modalSelector = '.modal.fade.in';
      
      const mockLocator = {
        isVisible: vi.fn().mockResolvedValue(true),
      };
      
      vi.mocked(mockPage.locator).mockReturnValue(mockLocator as unknown as ReturnType<Page['locator']>);

      const isWizardModalDismissed = async (): Promise<boolean> => {
        const modalVisible = await mockPage.locator(modalSelector).isVisible().catch(() => false);
        
        if (modalVisible) {
          return false;
        }
        
        await mockPage.waitForTimeout(500);
        
        const stillNotVisible = !await mockPage.locator(modalSelector).isVisible().catch(() => false);
        
        return stillNotVisible;
      };

      const result = await isWizardModalDismissed();

      expect(result).toBe(false);
      // Should not wait or check again if modal is visible
      expect(mockPage.waitForTimeout).not.toHaveBeenCalled();
      expect(mockLocator.isVisible).toHaveBeenCalledTimes(1);
    });
  });
});