import { render, screen, waitFor } from "@testing-library/react";
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { AgentStatusWidget } from "../AgentStatusWidget";

describe("AgentStatusWidget", () => {
  const mockFetch = vi.fn();

  beforeEach(() => {
    global.fetch = mockFetch as unknown as typeof fetch;
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  it("should render loading state initially", () => {
    mockFetch.mockImplementation(
      // eslint-disable-next-line @typescript-eslint/no-empty-function
      () => new Promise(() => {}) // Never resolves
    );

    render(<AgentStatusWidget id="test-widget" config={{}} />);

    expect(screen.getByText("Loading agents...")).toBeInTheDocument();
  });

  it("should fetch and display agents from API", async () => {
    const mockAgents = [
      {
        agentId: "agent-1",
        taskId: "task-1",
        status: "running",
        agentType: "worker",
        spawnedAt: new Date().toISOString(),
      },
      {
        agentId: "agent-2",
        taskId: "task-2",
        status: "completed",
        agentType: "reviewer",
        spawnedAt: new Date().toISOString(),
        completedAt: new Date().toISOString(),
      },
    ];

    mockFetch.mockResolvedValue({
      ok: true,
      json: () => Promise.resolve(mockAgents),
    });

    render(<AgentStatusWidget id="test-widget" config={{}} />);

    await waitFor(() => {
      expect(screen.getByText("Worker Agent")).toBeInTheDocument();
      expect(screen.getByText("Code Review Agent")).toBeInTheDocument();
    });

    expect(screen.getByText("Task: task-1")).toBeInTheDocument();
    expect(screen.getByText("Task: task-2")).toBeInTheDocument();
  });

  it("should display error message when fetch fails", async () => {
    mockFetch.mockResolvedValue({
      ok: false,
      statusText: "Internal Server Error",
    });

    render(<AgentStatusWidget id="test-widget" config={{}} />);

    await waitFor(() => {
      expect(screen.getByText(/Failed to fetch agents: Internal Server Error/)).toBeInTheDocument();
    });
  });

  it("should display no agents message when list is empty", async () => {
    mockFetch.mockResolvedValue({
      ok: true,
      json: () => Promise.resolve([]),
    });

    render(<AgentStatusWidget id="test-widget" config={{}} />);

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

  it("should display agent error messages", async () => {
    const mockAgents = [
      {
        agentId: "agent-1",
        taskId: "task-1",
        status: "failed",
        agentType: "tester",
        spawnedAt: new Date().toISOString(),
        error: "Test execution failed",
      },
    ];

    mockFetch.mockResolvedValue({
      ok: true,
      json: () => Promise.resolve(mockAgents),
    });

    render(<AgentStatusWidget id="test-widget" config={{}} />);

    await waitFor(() => {
      expect(screen.getByText("Test execution failed")).toBeInTheDocument();
    });
  });

  it("should display correct stats summary", async () => {
    const mockAgents = [
      {
        agentId: "agent-1",
        taskId: "task-1",
        status: "running",
        agentType: "worker",
        spawnedAt: new Date().toISOString(),
      },
      {
        agentId: "agent-2",
        taskId: "task-2",
        status: "running",
        agentType: "reviewer",
        spawnedAt: new Date().toISOString(),
      },
      {
        agentId: "agent-3",
        taskId: "task-3",
        status: "failed",
        agentType: "tester",
        spawnedAt: new Date().toISOString(),
      },
    ];

    mockFetch.mockResolvedValue({
      ok: true,
      json: () => Promise.resolve(mockAgents),
    });

    render(<AgentStatusWidget id="test-widget" config={{}} />);

    await waitFor(() => {
      // Check stats: 3 total, 2 working, 0 idle, 1 error
      const stats = screen.getAllByText(/^[0-9]+$/);
      expect(stats[0]).toHaveTextContent("3"); // Total
      expect(stats[1]).toHaveTextContent("2"); // Working
      expect(stats[2]).toHaveTextContent("0"); // Idle
      expect(stats[3]).toHaveTextContent("1"); // Error
    });
  });
});
