import { flushPromises, mount } from '@vue/test-utils';

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import CheckUpdates from './check-updates.vue';

const { modalOpen } = vi.hoisted(() => ({
  modalOpen: vi.fn(),
}));

vi.mock('@easyflow/locales', () => ({
  $t: (key: string) => key,
}));

vi.mock('@easyflow-core/popup-ui', () => ({
  useEasyFlowModal: () => [
    {
      name: 'UpdateNoticeModalStub',
      template: '<div><slot /></div>',
    },
    { open: modalOpen },
  ],
}));

describe('check updates visibility lifecycle', () => {
  let hidden = false;

  beforeEach(() => {
    hidden = false;
    modalOpen.mockClear();
    vi.useFakeTimers();
    vi.spyOn(document, 'hidden', 'get').mockImplementation(() => hidden);
    vi.stubGlobal('location', { hostname: 'customer.example' });
    vi.stubGlobal(
      'fetch',
      vi.fn().mockResolvedValue({
        headers: {
          get: (name: string) => (name === 'etag' ? 'version-1' : null),
        },
      }),
    );
  });

  afterEach(() => {
    vi.useRealTimers();
    vi.restoreAllMocks();
    vi.unstubAllGlobals();
  });

  it('restarts polling without fetching immediately when the page becomes visible', async () => {
    const wrapper = mount(CheckUpdates);
    const fetchMock = vi.mocked(fetch);

    hidden = true;
    document.dispatchEvent(new Event('visibilitychange'));
    hidden = false;
    document.dispatchEvent(new Event('visibilitychange'));

    expect(fetchMock).not.toHaveBeenCalled();

    await vi.advanceTimersByTimeAsync(59_999);
    expect(fetchMock).not.toHaveBeenCalled();

    await vi.advanceTimersByTimeAsync(1);
    await flushPromises();

    expect(fetchMock).toHaveBeenCalledTimes(1);
    expect(fetchMock).toHaveBeenCalledWith(
      '/',
      expect.objectContaining({ method: 'HEAD' }),
    );
    expect(modalOpen).not.toHaveBeenCalled();

    wrapper.unmount();
  });
});
