// @vitest-environment jsdom
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { act, fireEvent, render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { AppContext, type AppContextValue } from '../../context/AppContext';
import { ThemeProvider } from '../theme/ThemeProvider';
import { Header } from './Header';

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

vi.mock('../../lib/marketApi', () => ({
  fetchMarketIndices: (...args: any[]) => fetchMarketIndicesMock(...args),
}));

const appContext: AppContextValue = {
  botState: {
    settings: {},
    symbols: {},
    health: {},
    alerts: [],
    positions: [],
    orders: [],
    history: [],
    uptime: 0,
  } as any,
  socket: null,
  connected: true,
  activeSymbol: 'AAPL',
  setActiveSymbol: vi.fn(),
  isAdmin: false,
  user: { id: 'u1' },
  profile: {},
  showBacktestTab: false,
  showMarketplaceTab: false,
  handleSignOut: vi.fn(),
};

function setVisibilityState(value: DocumentVisibilityState) {
  Object.defineProperty(document, 'visibilityState', {
    configurable: true,
    value,
  });
}

function renderHeader() {
  return render(
    <ThemeProvider>
      <AppContext.Provider value={appContext}>
        <MemoryRouter>
          <Header />
        </MemoryRouter>
      </AppContext.Provider>
    </ThemeProvider>,
  );
}

describe('Header market index polling', () => {
  beforeEach(() => {
    vi.useFakeTimers();
    fetchMarketIndicesMock.mockReset();
    fetchMarketIndicesMock.mockResolvedValue([]);
    setVisibilityState('visible');
  });

  afterEach(() => {
    vi.useRealTimers();
    setVisibilityState('visible');
  });

  it('pauses index polling while the document is hidden and resumes when visible', async () => {
    setVisibilityState('hidden');
    renderHeader();

    expect(fetchMarketIndicesMock).not.toHaveBeenCalled();
    act(() => {
      vi.advanceTimersByTime(60_000);
    });
    expect(fetchMarketIndicesMock).not.toHaveBeenCalled();

    setVisibilityState('visible');
    act(() => {
      document.dispatchEvent(new Event('visibilitychange'));
    });
    expect(fetchMarketIndicesMock).toHaveBeenCalledTimes(1);

    act(() => {
      vi.advanceTimersByTime(60_000);
    });
    expect(fetchMarketIndicesMock).toHaveBeenCalledTimes(2);
  });

  it('focuses ticker search with Cmd/Ctrl-K', () => {
    renderHeader();

    const search = screen.getByLabelText('Search ticker');
    expect(search).not.toHaveFocus();

    fireEvent.keyDown(window, { key: 'k', metaKey: true });
    expect(search).toHaveFocus();
  });
});
