import { describe, it, expect } from 'vitest';
import { screen, waitFor } from '@testing-library/react';
import { renderRoute } from './render';

describe('Document Detail page', () => {
  it('renders document title', async () => {
    renderRoute('/documents/d1');
    await waitFor(() => {
      expect(screen.getByText('Apple Q4 Earnings Beat')).toBeInTheDocument();
    });
  });

  it('shows document type and source type', async () => {
    renderRoute('/documents/d1');
    await waitFor(() => {
      expect(screen.getByText('news')).toBeInTheDocument();
    });
    expect(screen.getByText('news_api')).toBeInTheDocument();
  });

  it('shows publisher', async () => {
    renderRoute('/documents/d1');
    await waitFor(() => {
      expect(screen.getByText('Reuters')).toBeInTheDocument();
    });
  });

  it('renders metadata section', async () => {
    renderRoute('/documents/d1');
    await waitFor(() => {
      expect(screen.getByText('Metadata')).toBeInTheDocument();
    });
    expect(screen.getByText('Language')).toBeInTheDocument();
    expect(screen.getByText('en')).toBeInTheDocument();
    expect(screen.getByText('Content Hash')).toBeInTheDocument();
  });

  it('renders parse quality score', async () => {
    renderRoute('/documents/d1');
    await waitFor(() => {
      expect(screen.getByText('Parse Quality')).toBeInTheDocument();
    });
    expect(screen.getByText('0.92')).toBeInTheDocument();
  });

  it('shows no intelligence message when null', async () => {
    renderRoute('/documents/d1');
    await waitFor(() => {
      expect(screen.getByText('No intelligence extraction available')).toBeInTheDocument();
    });
  });

  it('renders storage references section', async () => {
    renderRoute('/documents/d1');
    await waitFor(() => {
      expect(screen.getByText('Storage References')).toBeInTheDocument();
    });
  });
});

describe('Recommendation Detail page', () => {
  it('renders ticker as heading', async () => {
    renderRoute('/recommendations/r1');
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'AAPL' })).toBeInTheDocument();
    });
  });

  it('shows action and mode badges', async () => {
    renderRoute('/recommendations/r1');
    await waitFor(() => {
      expect(screen.getByText('buy')).toBeInTheDocument();
    });
    expect(screen.getByText('paper')).toBeInTheDocument();
  });

  it('shows time horizon', async () => {
    renderRoute('/recommendations/r1');
    await waitFor(() => {
      expect(screen.getByText('Horizon')).toBeInTheDocument();
    });
    expect(screen.getByText('7d')).toBeInTheDocument();
  });

  it('shows risk classification', async () => {
    renderRoute('/recommendations/r1');
    await waitFor(() => {
      expect(screen.getByText('Risk')).toBeInTheDocument();
    });
    expect(screen.getByText('moderate')).toBeInTheDocument();
  });

  it('shows portfolio and max loss percentages', async () => {
    renderRoute('/recommendations/r1');
    await waitFor(() => {
      expect(screen.getByText('Portfolio %')).toBeInTheDocument();
    });
    expect(screen.getByText('5.0%')).toBeInTheDocument();
    expect(screen.getByText('2.00%')).toBeInTheDocument();
  });

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

  it('shows evidence section with zero count', async () => {
    renderRoute('/recommendations/r1');
    await waitFor(() => {
      expect(screen.getByText('Evidence (0)')).toBeInTheDocument();
    });
    expect(screen.getByText('No evidence linked')).toBeInTheDocument();
  });
});

describe('Trend Detail page', () => {
  it('renders entity ID as heading', async () => {
    renderRoute('/trends/t1');
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'AAPL' })).toBeInTheDocument();
    });
  });

  it('shows trend direction', async () => {
    renderRoute('/trends/t1');
    await waitFor(() => {
      expect(screen.getByText('bullish')).toBeInTheDocument();
    });
  });

  it('shows window badge', async () => {
    renderRoute('/trends/t1');
    await waitFor(() => {
      expect(screen.getByText('AAPL')).toBeInTheDocument();
    });
    expect(screen.getAllByText('7d').length).toBeGreaterThanOrEqual(1);
  });

  it('shows contradiction score', async () => {
    renderRoute('/trends/t1');
    await waitFor(() => {
      expect(screen.getByText('Contradiction')).toBeInTheDocument();
    });
    expect(screen.getByText('10%')).toBeInTheDocument();
  });

  it('shows dominant catalysts', async () => {
    renderRoute('/trends/t1');
    await waitFor(() => {
      expect(screen.getByText('Dominant Catalysts')).toBeInTheDocument();
    });
    expect(screen.getByText('earnings')).toBeInTheDocument();
  });

  it('shows contributing evidence section', async () => {
    renderRoute('/trends/t1');
    await waitFor(() => {
      expect(screen.getByText('Contributing Evidence (0)')).toBeInTheDocument();
    });
    expect(screen.getByText('No evidence records')).toBeInTheDocument();
  });

  it('shows trend projection panel', async () => {
    renderRoute('/trends/t1');
    await waitFor(() => {
      expect(screen.getByText('Trend Projection')).toBeInTheDocument();
    });
    // Mock projection: projected_direction: 'bearish', diverges_from_current: true
    expect(screen.getByText('DIVERGENCE')).toBeInTheDocument();
    expect(screen.getByText('bearish')).toBeInTheDocument();
  });

  it('shows macro contribution percentage', async () => {
    renderRoute('/trends/t1');
    await waitFor(() => {
      expect(screen.getByText('Macro Contribution')).toBeInTheDocument();
    });
    // macro_contribution_pct: 0.3 → 30%
    expect(screen.getByText('30%')).toBeInTheDocument();
  });
});

describe('Global Event Detail page', () => {
  it('renders page heading', async () => {
    renderRoute('/macro/events/me1');
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Global Event' })).toBeInTheDocument();
    });
  });

  it('shows severity badge', async () => {
    renderRoute('/macro/events/me1');
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'Global Event' })).toBeInTheDocument();
    });
    // severity: 'high'
    expect(screen.getByText('high')).toBeInTheDocument();
  });

  it('shows event summary', async () => {
    renderRoute('/macro/events/me1');
    await waitFor(() => {
      expect(screen.getByText('Summary')).toBeInTheDocument();
    });
    expect(screen.getByText('US tariffs on Chinese semiconductors')).toBeInTheDocument();
  });

  it('shows key facts', async () => {
    renderRoute('/macro/events/me1');
    await waitFor(() => {
      expect(screen.getByText('Key Facts')).toBeInTheDocument();
    });
    expect(screen.getByText('25% tariff')).toBeInTheDocument();
    expect(screen.getByText('Effective in 30 days')).toBeInTheDocument();
  });

  it('shows affected regions', async () => {
    renderRoute('/macro/events/me1');
    await waitFor(() => {
      expect(screen.getByText('Regions')).toBeInTheDocument();
    });
    expect(screen.getByText('US')).toBeInTheDocument();
    expect(screen.getByText('CN')).toBeInTheDocument();
  });

  it('shows affected companies table', async () => {
    renderRoute('/macro/events/me1');
    await waitFor(() => {
      expect(screen.getByText(/Affected Companies/)).toBeInTheDocument();
    });
    // Mock has 1 impact: AAPL with negative direction
    expect(screen.getByText('AAPL')).toBeInTheDocument();
    expect(screen.getByText('negative')).toBeInTheDocument();
  });

  it('shows estimated duration', async () => {
    renderRoute('/macro/events/me1');
    await waitFor(() => {
      expect(screen.getByText('medium term')).toBeInTheDocument();
    });
  });
});

describe('Company Detail page', () => {
  it('renders company ticker as heading', async () => {
    renderRoute('/companies/1');
    await waitFor(() => {
      expect(screen.getByRole('heading', { name: 'AAPL' })).toBeInTheDocument();
    });
  });

  it('shows company name', async () => {
    renderRoute('/companies/1');
    await waitFor(() => {
      expect(screen.getByText('Apple Inc.')).toBeInTheDocument();
    });
  });

  it('shows sector and exchange', async () => {
    renderRoute('/companies/1');
    await waitFor(() => {
      expect(screen.getByText('NASDAQ')).toBeInTheDocument();
    });
  });
});
