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

import { describe, it, expect, vi } from 'vitest';
import { render } from 'ink-testing-library';
import { Text } from 'ink';
import { App } from './App.js';
import { UIStateContext, type UIState } from './contexts/UIStateContext.js';
import { StreamingState } from './types.js';

// Mock components to isolate App component testing
vi.mock('./components/MainContent.js', () => ({
  MainContent: () => <Text>MainContent</Text>,
}));

vi.mock('./components/DialogManager.js', () => ({
  DialogManager: () => <Text>DialogManager</Text>,
}));

vi.mock('./components/Composer.js', () => ({
  Composer: () => <Text>Composer</Text>,
}));

vi.mock('./components/Notifications.js', () => ({
  Notifications: () => <Text>Notifications</Text>,
}));

vi.mock('./components/QuittingDisplay.js', () => ({
  QuittingDisplay: () => <Text>Quitting...</Text>,
}));

vi.mock('./components/Footer.js', () => ({
  Footer: () => <Text>Footer</Text>,
}));

vi.mock('./semantic-colors.js', () => ({
  theme: {
    status: {
      warning: 'yellow',
    },
  },
}));

// Don't mock the layout components - let them render normally so tests can see the Ctrl messages

vi.mock('./hooks/useLayoutConfig.js', () => ({
  useLayoutConfig: () => ({
    mode: 'default',
    shouldUseStatic: true,
    shouldShowFooterInComposer: true,
  }),
}));

vi.mock('./hooks/useFooterProps.js', () => ({
  useFooterProps: () => ({
    model: 'test-model',
    targetDir: '/test',
    debugMode: false,
    branchName: 'test-branch',
    debugMessage: '',
    corgiMode: false,
    errorCount: 0,
    showErrorDetails: false,
    showMemoryUsage: false,
    promptTokenCount: 0,
    nightly: false,
    isTrustedFolder: true,
    vimMode: undefined,
  }),
}));

describe('App', () => {
  const mockUIState: Partial<UIState> = {
    streamingState: StreamingState.Idle,
    quittingMessages: null,
    dialogsVisible: false,
    mainControlsRef: { current: null },
    historyManager: {
      addItem: vi.fn(),
      history: [],
      updateItem: vi.fn(),
      clearItems: vi.fn(),
      loadHistory: vi.fn(),
    },
  };

  it('should render main content and composer when not quitting', () => {
    const { lastFrame } = render(
      <UIStateContext.Provider value={mockUIState as UIState}>
        <App />
      </UIStateContext.Provider>,
    );

    expect(lastFrame()).toContain('MainContent');
    expect(lastFrame()).toContain('Composer');
  });

  it('should render quitting display when quittingMessages is set', () => {
    const quittingUIState = {
      ...mockUIState,
      quittingMessages: [{ id: 1, type: 'user', text: 'test' }],
    } as UIState;

    const { lastFrame } = render(
      <UIStateContext.Provider value={quittingUIState}>
        <App />
      </UIStateContext.Provider>,
    );

    expect(lastFrame()).toContain('Quitting...');
  });

  it('should render dialog manager when dialogs are visible', () => {
    const dialogUIState = {
      ...mockUIState,
      dialogsVisible: true,
    } as UIState;

    const { lastFrame } = render(
      <UIStateContext.Provider value={dialogUIState}>
        <App />
      </UIStateContext.Provider>,
    );

    expect(lastFrame()).toContain('MainContent');
    expect(lastFrame()).toContain('DialogManager');
  });

  it('should show Ctrl+C exit prompt when dialogs are visible and ctrlCPressedOnce is true', () => {
    const ctrlCUIState = {
      ...mockUIState,
      dialogsVisible: true,
      ctrlCPressedOnce: true,
    } as UIState;

    const { lastFrame } = render(
      <UIStateContext.Provider value={ctrlCUIState}>
        <App />
      </UIStateContext.Provider>,
    );

    expect(lastFrame()).toContain('Press Ctrl+C again to exit.');
  });

  it('should show Ctrl+D exit prompt when dialogs are visible and ctrlDPressedOnce is true', () => {
    const ctrlDUIState = {
      ...mockUIState,
      dialogsVisible: true,
      ctrlDPressedOnce: true,
    } as UIState;

    const { lastFrame } = render(
      <UIStateContext.Provider value={ctrlDUIState}>
        <App />
      </UIStateContext.Provider>,
    );

    expect(lastFrame()).toContain('Press Ctrl+D again to exit.');
  });
});
