/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { useSnowfall } from './useSnowfall.js';
import { themeManager } from '../themes/theme-manager.js';
import { renderHookWithProviders } from '../../test-utils/render.js';
import { act } from 'react';
import { debugState } from '../debug.js';
import type { Theme } from '../themes/theme.js';
import type { UIState } from '../contexts/UIStateContext.js';

vi.mock('../themes/theme-manager.js', () => ({
  themeManager: {
    getActiveTheme: vi.fn(),
    setTerminalBackground: vi.fn(),
    getAllThemes: vi.fn(() => []),
    setActiveTheme: vi.fn(),
  },
  DEFAULT_THEME: { name: 'Default' },
}));

vi.mock('../themes/builtin/dark/holiday-dark.js', () => ({
  Holiday: { name: 'Holiday' },
}));

vi.mock('./useTerminalSize.js', () => ({
  useTerminalSize: vi.fn(() => ({ columns: 120, rows: 20 })),
}));

describe('useSnowfall', () => {
  const mockArt = 'LOGO';

  beforeEach(() => {
    vi.clearAllMocks();
    vi.useFakeTimers();
    vi.mocked(themeManager.getActiveTheme).mockReturnValue({
      name: 'Holiday',
    } as Theme);
    vi.setSystemTime(new Date('2025-12-25'));
    debugState.debugNumAnimatedComponents = 0;
  });

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

  it('initially enables animation during holiday season with Holiday theme', async () => {
    const { result } = await renderHookWithProviders(
      () => useSnowfall(mockArt),
      {
        uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
      },
    );

    // Should contain holiday trees
    expect(result.current).toContain('|_|');
    // Should have started animation
    expect(debugState.debugNumAnimatedComponents).toBeGreaterThan(0);
  });

  it('stops animation after 15 seconds', async () => {
    const { result } = await renderHookWithProviders(
      () => useSnowfall(mockArt),
      {
        uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
      },
    );

    expect(debugState.debugNumAnimatedComponents).toBeGreaterThan(0);

    act(() => {
      vi.advanceTimersByTime(15001);
    });

    // Animation should be stopped
    expect(debugState.debugNumAnimatedComponents).toBe(0);
    // Should no longer contain trees
    expect(result.current).toBe(mockArt);
  });

  it('does not enable animation if not holiday season', async () => {
    vi.setSystemTime(new Date('2025-06-15'));
    const { result } = await renderHookWithProviders(
      () => useSnowfall(mockArt),
      {
        uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
      },
    );

    expect(result.current).toBe(mockArt);
    expect(debugState.debugNumAnimatedComponents).toBe(0);
  });

  it('does not enable animation if theme is not Holiday', async () => {
    vi.mocked(themeManager.getActiveTheme).mockReturnValue({
      name: 'Default',
    } as Theme);
    const { result } = await renderHookWithProviders(
      () => useSnowfall(mockArt),
      {
        uiState: { history: [], historyRemountKey: 0 } as Partial<UIState>,
      },
    );

    expect(result.current).toBe(mockArt);
    expect(debugState.debugNumAnimatedComponents).toBe(0);
  });

  it('does not enable animation if chat has started', async () => {
    const { result } = await renderHookWithProviders(
      () => useSnowfall(mockArt),
      {
        uiState: {
          history: [{ type: 'user', text: 'hello' }],
          historyRemountKey: 0,
        } as Partial<UIState>,
      },
    );

    expect(result.current).toBe(mockArt);
    expect(debugState.debugNumAnimatedComponents).toBe(0);
  });
});
