import { describe, it, expect, vi } from 'vitest';
import { screen, waitFor } from '@testing-library/react';
import { http, HttpResponse } from 'msw';
import { server } from '../../mocks/server';
import { renderWithProviders } from '../../test/utils';
import DashboardPage from '../DashboardPage';

vi.mock('../../components/TimeAgo', () => ({
  default: ({ date }: { date: string }) => <span>{date}</span>,
}));

describe('DashboardPage', () => {
  it('renders the dashboard heading and new task link', () => {
    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });
    expect(screen.getByText('Dashboard')).toBeInTheDocument();
    expect(screen.getByText('New Task')).toBeInTheDocument();
  });

  it('renders stat cards with data from API', async () => {
    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    await waitFor(() => {
      expect(screen.getByText('Total')).toBeInTheDocument();
    });

    expect(screen.getByText('Running')).toBeInTheDocument();
    expect(screen.getByText('Queued')).toBeInTheDocument();
    expect(screen.getByText('Completed')).toBeInTheDocument();
    expect(screen.getByText('Failed')).toBeInTheDocument();
  });

  it('shows stat values once loaded', async () => {
    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    // Total tasks count from mock data (limited to 10 by API call)
    await waitFor(() => {
      const totalCard = screen.getByText('Total').closest('div')!;
      const value = totalCard.querySelector('p:last-child');
      expect(value).not.toBeNull();
      expect(value!.textContent).not.toBe('-');
    });
  });

  it('renders recent tasks section with task names', async () => {
    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    expect(screen.getByText('Recent Tasks')).toBeInTheDocument();

    await waitFor(() => {
      expect(screen.getByText('fix-auth-bug')).toBeInTheDocument();
    });
  });

  it('renders task names as links to detail pages', async () => {
    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    await waitFor(() => {
      const link = screen.getByText('fix-auth-bug').closest('a');
      expect(link).toHaveAttribute('href', '/tasks/default/fix-auth-bug');
    });
  });

  it('renders agents sidebar', async () => {
    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    expect(screen.getByText('Agents')).toBeInTheDocument();

    await waitFor(() => {
      expect(screen.getByText('opencode-agent')).toBeInTheDocument();
    });
  });

  it('renders agent names as links to detail pages', async () => {
    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    await waitFor(() => {
      const link = screen.getByText('opencode-agent').closest('a');
      expect(link).toHaveAttribute('href', '/agents/default/opencode-agent');
    });
  });

  it('shows agent status badges', async () => {
    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    await waitFor(() => {
      // All agents should have status badges (Live, Starting, or Suspended)
      const liveBadges = screen.getAllByText('Live');
      expect(liveBadges.length).toBeGreaterThan(0);
    });
  });

  it('shows "View all" links', async () => {
    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    const viewAllLinks = screen.getAllByText('View all');
    expect(viewAllLinks.length).toBe(2); // tasks + agents
  });

  it('shows empty state when no tasks exist', async () => {
    server.use(
      http.get('/api/v1/tasks', () => {
        return HttpResponse.json({
          tasks: [],
          total: 0,
          pagination: { limit: 10, offset: 0, totalCount: 0, hasMore: false },
        });
      })
    );

    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    await waitFor(() => {
      expect(screen.getByText(/No tasks yet/)).toBeInTheDocument();
    });

    expect(screen.getByText('Create your first task')).toBeInTheDocument();
  });

  it('shows empty state when no agents exist', async () => {
    server.use(
      http.get('/api/v1/agents', () => {
        return HttpResponse.json({
          agents: [],
          total: 0,
          pagination: { limit: 100, offset: 0, totalCount: 0, hasMore: false },
        });
      })
    );

    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    await waitFor(() => {
      expect(screen.getByText('No agents configured')).toBeInTheDocument();
    });
  });

  it('shows loading dashes while data is fetching', () => {
    server.use(
      http.get('/api/v1/tasks', async () => {
        await new Promise((r) => setTimeout(r, 200));
        return HttpResponse.json({ tasks: [], total: 0 });
      }),
      http.get('/api/v1/agents', async () => {
        await new Promise((r) => setTimeout(r, 200));
        return HttpResponse.json({ agents: [], total: 0 });
      })
    );

    renderWithProviders(<DashboardPage />, { initialEntries: ['/'] });

    // Stat cards show '-' when loading
    const dashes = screen.getAllByText('-');
    expect(dashes.length).toBe(5); // 5 stat cards
  });
});
