import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import { TaskList } from "./TaskList";
import { TaskStatus, TaskPriority, type Task } from "@mosaic/shared";

describe("TaskList", (): void => {
  const mockTasks: Task[] = [
    {
      id: "task-1",
      title: "Review pull request",
      description: "Review and provide feedback on frontend PR",
      status: TaskStatus.IN_PROGRESS,
      priority: TaskPriority.HIGH,
      dueDate: new Date("2026-01-29"),
      creatorId: "user-1",
      assigneeId: "user-1",
      workspaceId: "workspace-1",
      projectId: null,
      parentId: null,
      sortOrder: 0,
      metadata: {},
      completedAt: null,
      createdAt: new Date("2026-01-28"),
      updatedAt: new Date("2026-01-28"),
    },
    {
      id: "task-2",
      title: "Update documentation",
      description: "Add setup instructions",
      status: TaskStatus.NOT_STARTED,
      priority: TaskPriority.MEDIUM,
      dueDate: new Date("2026-02-05"),
      creatorId: "user-1",
      assigneeId: "user-1",
      workspaceId: "workspace-1",
      projectId: null,
      parentId: null,
      sortOrder: 1,
      metadata: {},
      completedAt: null,
      createdAt: new Date("2026-01-28"),
      updatedAt: new Date("2026-01-28"),
    },
  ];

  it("should render empty state when no tasks", (): void => {
    render(<TaskList tasks={[]} isLoading={false} />);
    expect(screen.getByText(/no tasks scheduled/i)).toBeInTheDocument();
  });

  it("should render loading state", (): void => {
    render(<TaskList tasks={[]} isLoading={true} />);
    expect(screen.getByText(/loading/i)).toBeInTheDocument();
  });

  it("should render tasks list", (): void => {
    render(<TaskList tasks={mockTasks} isLoading={false} />);
    expect(screen.getByText("Review pull request")).toBeInTheDocument();
    expect(screen.getByText("Update documentation")).toBeInTheDocument();
  });

  it("should group tasks by date", (): void => {
    render(<TaskList tasks={mockTasks} isLoading={false} />);
    // Should have date group sections (Today, This Week, etc.)
    // The exact sections depend on the current date, so just verify grouping works
    const sections = screen.getAllByRole("heading", { level: 2 });
    expect(sections.length).toBeGreaterThan(0);
  });

  it("should use PDA-friendly language", (): void => {
    render(<TaskList tasks={mockTasks} isLoading={false} />);
    // Should NOT contain demanding language
    const text = screen.getByRole("main").textContent;
    expect(text).not.toMatch(/overdue/i);
    expect(text).not.toMatch(/urgent/i);
    expect(text).not.toMatch(/must do/i);
  });

  it("should display status indicators", (): void => {
    render(<TaskList tasks={mockTasks} isLoading={false} />);
    // Check for emoji status indicators (rendered as text)
    const listItems = screen.getAllByRole("listitem");
    expect(listItems.length).toBe(mockTasks.length);
  });

  describe("error states", (): void => {
    it("should handle undefined tasks gracefully", (): void => {
      render(<TaskList tasks={undefined as unknown as Task[]} isLoading={false} />);
      expect(screen.getByText(/no tasks scheduled/i)).toBeInTheDocument();
    });

    it("should handle null tasks gracefully", (): void => {
      render(<TaskList tasks={null as unknown as Task[]} isLoading={false} />);
      expect(screen.getByText(/no tasks scheduled/i)).toBeInTheDocument();
    });

    it("should handle tasks with missing required fields", (): void => {
      const firstTask = mockTasks[0];
      if (!firstTask) {
        throw new Error("Mock task not found");
      }
      const malformedTasks: Task[] = [
        {
          ...firstTask,
          title: "", // Empty title
        },
      ];

      render(<TaskList tasks={malformedTasks} isLoading={false} />);
      // Component should render without crashing
      expect(screen.getByRole("main")).toBeInTheDocument();
    });

    it("should handle tasks with invalid dates", (): void => {
      const firstTask = mockTasks[0];
      if (!firstTask) {
        throw new Error("Mock task not found");
      }
      const tasksWithBadDates: Task[] = [
        {
          ...firstTask,
          dueDate: new Date("invalid-date"),
        },
      ];

      render(<TaskList tasks={tasksWithBadDates} isLoading={false} />);
      expect(screen.getByRole("main")).toBeInTheDocument();
    });

    it("should handle extremely large task lists", (): void => {
      const firstTask = mockTasks[0];
      if (!firstTask) {
        throw new Error("Mock task not found");
      }
      const largeTasks: Task[] = Array.from({ length: 1000 }, (_, i) => ({
        ...firstTask,
        id: `task-${String(i)}`,
        title: `Task ${String(i)}`,
      }));

      render(<TaskList tasks={largeTasks} isLoading={false} />);
      expect(screen.getByRole("main")).toBeInTheDocument();
    });

    it("should handle tasks with very long titles", (): void => {
      const firstTask = mockTasks[0];
      if (!firstTask) {
        throw new Error("Mock task not found");
      }
      const longTitleTask: Task = {
        ...firstTask,
        title: "A".repeat(500),
      };

      render(<TaskList tasks={[longTitleTask]} isLoading={false} />);
      expect(screen.getByText(/A{500}/)).toBeInTheDocument();
    });

    it("should handle tasks with special characters in title", (): void => {
      const firstTask = mockTasks[0];
      if (!firstTask) {
        throw new Error("Mock task not found");
      }
      const specialCharTask: Task = {
        ...firstTask,
        title: '<script>alert("xss")</script>',
      };

      render(<TaskList tasks={[specialCharTask]} isLoading={false} />);
      // Should render escaped, not execute
      expect(screen.getByRole("main").innerHTML).not.toContain("<script>");
    });
  });
});
