import { describe, it, expect } from 'vitest';
import { screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { HttpResponse, http } from 'msw';
import { renderRoute } from './render';
import { server } from './mocks/server';

describe('Recommendations page', () => {
  // -------------------------------------------------------------------------
  // 1. Renders recommendation list with ticker
  // -------------------------------------------------------------------------
  it('renders recommendation with ticker', async () => {
    renderRoute('/recommendations');
    await waitFor(() => {
      expect(screen.getByText('AAPL')).toBeInTheDocument();
    });
  });

  // -------------------------------------------------------------------------
  // 2. Shows action badge
  // -------------------------------------------------------------------------
  it('shows action badge (buy)', async () => {
    renderRoute('/recommendations');
    await waitFor(() => {
      expect(screen.getByText('buy')).toBeInTheDocument();
    });
  });

  // -------------------------------------------------------------------------
  // 3. Shows mode badge
  // -------------------------------------------------------------------------
  it('shows mode badge (paper)', async () => {
    renderRoute('/recommendations');
    await waitFor(() => {
      expect(screen.getByText('paper')).toBeInTheDocument();
    });
  });

  // -------------------------------------------------------------------------
  // 4. Shows thesis text
  // -------------------------------------------------------------------------
  it('shows thesis text', async () => {
    renderRoute('/recommendations');
    await waitFor(() => {
      expect(screen.getByText('Strong earnings momentum')).toBeInTheDocument();
    });
  });

  // -------------------------------------------------------------------------
  // 5. Risk tier filter renders with options
  // -------------------------------------------------------------------------
  it('renders risk tier filter with options', async () => {
    renderRoute('/recommendations');
    await waitFor(() => {
      expect(screen.getByLabelText('Risk Tier')).toBeInTheDocument();
    });
    const select = screen.getByLabelText('Risk Tier');
    const options = within(select).getAllByRole('option');
    expect(options).toHaveLength(3);
    expect(options[0]).toHaveTextContent('Conservative');
    expect(options[1]).toHaveTextContent('Moderate');
    expect(options[2]).toHaveTextContent('Aggressive');
  });

  // -------------------------------------------------------------------------
  // 6. Empty state
  // -------------------------------------------------------------------------
  it('shows empty state when no recommendations', async () => {
    server.use(
      http.get('/api/recommendations', () => HttpResponse.json([])),
    );
    renderRoute('/recommendations');
    await waitFor(() => {
      expect(screen.getByText('No data')).toBeInTheDocument();
    });
  });

  // -------------------------------------------------------------------------
  // 7. Page title renders
  // -------------------------------------------------------------------------
  it('renders page title', async () => {
    renderRoute('/recommendations');
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Recommendations' })).toBeInTheDocument();
    });
  });

  // -------------------------------------------------------------------------
  // 8. Multiple recommendations render
  // -------------------------------------------------------------------------
  it('renders multiple recommendations', async () => {
    server.use(
      http.get('/api/recommendations', () => HttpResponse.json([
        { id: 'r1', ticker: 'AAPL', action: 'buy', mode: 'paper', confidence: 0.78, time_horizon: '7d', thesis: 'Strong earnings', invalidation_conditions: null, portfolio_pct: 0.05, max_loss_pct: 0.02, model_version: 'v1', risk_classification: 'moderate', generated_at: '2026-04-10T19:00:00Z' },
        { id: 'r2', ticker: 'MSFT', action: 'sell', mode: 'paper', confidence: 0.65, time_horizon: '30d', thesis: 'Weakening outlook', invalidation_conditions: null, portfolio_pct: 0.03, max_loss_pct: 0.01, model_version: 'v1', risk_classification: 'conservative', generated_at: '2026-04-11T10:00:00Z' },
      ])),
    );
    renderRoute('/recommendations');
    await waitFor(() => {
      expect(screen.getByText('AAPL')).toBeInTheDocument();
    });
    expect(screen.getByText('MSFT')).toBeInTheDocument();
    expect(screen.getByText('sell')).toBeInTheDocument();
  });

  // -------------------------------------------------------------------------
  // 9. Risk tier filter changes selection
  // -------------------------------------------------------------------------
  it('allows changing risk tier', async () => {
    const user = userEvent.setup();
    renderRoute('/recommendations');
    await waitFor(() => {
      expect(screen.getByLabelText('Risk Tier')).toBeInTheDocument();
    });
    const select = screen.getByLabelText('Risk Tier');
    await user.selectOptions(select, 'aggressive');
    expect(select).toHaveValue('aggressive');
  });

  // -------------------------------------------------------------------------
  // 10. Ticker filter renders
  // -------------------------------------------------------------------------
  it('renders ticker filter', async () => {
    renderRoute('/recommendations');
    await waitFor(() => {
      expect(screen.getByPlaceholderText('Ticker…')).toBeInTheDocument();
    });
  });
});
