import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, waitFor, fireEvent } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import DashboardPage from '../DashboardPage'
import * as autopilotApi from '../../api/autopilot'
import { AutopilotSettingsProvider } from '../../contexts/AutopilotSettingsContext'
import { BrowserRouter } from 'react-router-dom'

vi.mock('../../api/autopilot')
vi.mock('../../api/trading')
vi.mock('../../api/marketData')
vi.mock('../../api/strategies')
vi.mock('../../components/WebSocketProvider', () => ({
  useWebSocketContext: () => ({ isConnected: true, lastMessage: null, subscribe: vi.fn(() => vi.fn()) }),
}))
vi.mock('../../contexts/SnackbarContext', () => ({
  useSnackbar: () => ({
    showError: vi.fn(),
    showSuccess: vi.fn(),
    showWarning: vi.fn(),
    showInfo: vi.fn(),
  }),
}))

describe('DashboardPage - Autopilot Section', () => {
  let queryClient: QueryClient

  beforeEach(() => {
    queryClient = new QueryClient({
      defaultOptions: { queries: { retry: false } },
    })
    vi.clearAllMocks()
  })

  // Helper to wrap component with all required providers
  const renderDashboard = () => {
    return render(
      <QueryClientProvider client={queryClient}>
        <BrowserRouter>
          <AutopilotSettingsProvider>
            <DashboardPage />
          </AutopilotSettingsProvider>
        </BrowserRouter>
      </QueryClientProvider>
    )
  }

  it('renders autopilot configuration section', async () => {
    const mockModeInfo = {
      modes: {
        pattern: { name: 'Pattern-Based', description: 'Test' },
        intelligent: { name: 'ML-Based', description: 'Test' },
      },
      comparison: {},
    }

    vi.mocked(autopilotApi.autopilotApi.getModes).mockResolvedValue(mockModeInfo as any)

    renderDashboard()

    await waitFor(() => {
      expect(screen.getByText('Autopilot Configuration')).toBeInTheDocument()
    })
  })

  it('displays mode selector', async () => {
    const mockModeInfo = {
      modes: {
        pattern: { name: 'Pattern-Based', description: 'Test' },
        intelligent: { name: 'ML-Based', description: 'Test' },
      },
      comparison: {},
    }

    vi.mocked(autopilotApi.autopilotApi.getModes).mockResolvedValue(mockModeInfo as any)

    renderDashboard()

    await waitFor(() => {
      expect(screen.getByText('Select Autopilot Mode')).toBeInTheDocument()
    })
  })

  it('shows auto-execute toggle', async () => {
    const mockModeInfo = {
      modes: {
        pattern: { name: 'Pattern-Based', description: 'Test' },
        intelligent: { name: 'ML-Based', description: 'Test' },
      },
      comparison: {},
    }

    vi.mocked(autopilotApi.autopilotApi.getModes).mockResolvedValue(mockModeInfo as any)

    renderDashboard()

    await waitFor(() => {
      expect(screen.getByText(/Auto-Execute/)).toBeInTheDocument()
    })
  })

  it('shows start button when autopilot is not running', async () => {
    const mockModeInfo = {
      modes: {
        pattern: { name: 'Pattern-Based', description: 'Test' },
        intelligent: { name: 'ML-Based', description: 'Test' },
      },
      comparison: {},
    }

    vi.mocked(autopilotApi.autopilotApi.getModes).mockResolvedValue(mockModeInfo as any)
    vi.mocked(autopilotApi.autopilotApi.getUnifiedStatus).mockResolvedValue({
      running: false,
      mode: 'pattern',
    } as any)

    renderDashboard()

    await waitFor(() => {
      expect(screen.getByText('Start AutoPilot')).toBeInTheDocument()
    })
  })

  it('shows stop button when autopilot is running', async () => {
    const mockModeInfo = {
      modes: {
        pattern: { name: 'Pattern-Based', description: 'Test' },
        intelligent: { name: 'ML-Based', description: 'Test' },
      },
      comparison: {},
    }

    vi.mocked(autopilotApi.autopilotApi.getModes).mockResolvedValue(mockModeInfo as any)
    vi.mocked(autopilotApi.autopilotApi.getUnifiedStatus).mockResolvedValue({
      running: true,
      mode: 'pattern',
    } as any)

    renderDashboard()

    await waitFor(() => {
      expect(screen.getByText('Stop AutoPilot')).toBeInTheDocument()
    })
  })

  it('calls startUnified when start button is clicked', async () => {
    const mockModeInfo = {
      modes: {
        pattern: { name: 'Pattern-Based', description: 'Test' },
        intelligent: { name: 'ML-Based', description: 'Test' },
      },
      comparison: {},
    }

    const startUnifiedMock = vi.fn().mockResolvedValue({ status: 'started' })
    vi.mocked(autopilotApi.autopilotApi.getModes).mockResolvedValue(mockModeInfo as any)
    vi.mocked(autopilotApi.autopilotApi.getUnifiedStatus).mockResolvedValue({
      running: false,
      mode: 'pattern',
    } as any)
    vi.mocked(autopilotApi.autopilotApi.startUnified).mockImplementation(startUnifiedMock)

    renderDashboard()

    await waitFor(() => {
      const startButton = screen.getByText('Start AutoPilot')
      fireEvent.click(startButton)
    })

    await waitFor(() => {
      expect(startUnifiedMock).toHaveBeenCalled()
    })
  })

  it('displays current mode in status chip', async () => {
    const mockModeInfo = {
      modes: {
        pattern: { name: 'Pattern-Based', description: 'Test' },
        intelligent: { name: 'ML-Based', description: 'Test' },
      },
      comparison: {},
    }

    vi.mocked(autopilotApi.autopilotApi.getModes).mockResolvedValue(mockModeInfo as any)
    vi.mocked(autopilotApi.autopilotApi.getUnifiedStatus).mockResolvedValue({
      running: true,
      mode: 'intelligent',
    } as any)

    renderDashboard()

    await waitFor(() => {
      expect(screen.getByText(/AutoPilot Active \(intelligent\)/)).toBeInTheDocument()
    })
  })
})
