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

// Mock @dnd-kit/sortable
vi.mock("@dnd-kit/sortable", () => ({
  useSortable: () => ({
    attributes: {},
    listeners: {},
    setNodeRef: vi.fn(),
    transform: null,
    transition: null,
    isDragging: false,
  }),
}));

const mockTask: Task = {
  id: "task-1",
  title: "Complete project documentation",
  description: "Write comprehensive docs for the API",
  status: TaskStatus.IN_PROGRESS,
  priority: TaskPriority.HIGH,
  dueDate: new Date("2026-02-01"),
  assigneeId: "user-1",
  creatorId: "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"),
};

describe("TaskCard", () => {
  describe("Rendering", () => {
    it("should render task title", () => {
      render(<TaskCard task={mockTask} />);

      expect(screen.getByText("Complete project documentation")).toBeInTheDocument();
    });

    it("should render as an article element for semantic HTML", () => {
      render(<TaskCard task={mockTask} />);

      const card = screen.getByRole("article");
      expect(card).toBeInTheDocument();
    });

    it("should display task priority", () => {
      render(<TaskCard task={mockTask} />);

      expect(screen.getByText("High")).toBeInTheDocument();
    });

    it("should display due date when available", () => {
      render(<TaskCard task={mockTask} />);

      // Check for formatted date (format: "Feb 1" or similar)
      const dueDateElement = screen.getByText(/Feb 1/);
      expect(dueDateElement).toBeInTheDocument();
    });

    it("should not display due date when null", () => {
      const taskWithoutDueDate = { ...mockTask, dueDate: null };
      render(<TaskCard task={taskWithoutDueDate} />);

      // Should not show any date
      expect(screen.queryByText(/Feb/)).not.toBeInTheDocument();
    });

    it("should truncate long titles gracefully", () => {
      const longTask = {
        ...mockTask,
        title: "This is a very long task title that should be truncated to prevent layout issues",
      };
      const { container } = render(<TaskCard task={longTask} />);

      const titleElement = container.querySelector("h4");
      expect(titleElement).toBeInTheDocument();
      // Should have text truncation classes
      expect(titleElement?.className).toMatch(/truncate|line-clamp/);
    });
  });

  describe("Priority Display", () => {
    it("should display HIGH priority with appropriate styling", () => {
      render(<TaskCard task={mockTask} />);

      const priorityBadge = screen.getByText("High");
      expect(priorityBadge).toBeInTheDocument();
    });

    it("should display MEDIUM priority", () => {
      const mediumTask = { ...mockTask, priority: TaskPriority.MEDIUM };
      render(<TaskCard task={mediumTask} />);

      expect(screen.getByText("Medium")).toBeInTheDocument();
    });

    it("should display LOW priority", () => {
      const lowTask = { ...mockTask, priority: TaskPriority.LOW };
      render(<TaskCard task={lowTask} />);

      expect(screen.getByText("Low")).toBeInTheDocument();
    });

    it("should use calm colors for priority badges (not aggressive red)", () => {
      const { container } = render(<TaskCard task={mockTask} />);

      const priorityBadge = screen.getByText("High").closest("span");
      const className = priorityBadge?.className || "";

      // Should not use harsh red for high priority
      expect(className).not.toMatch(/bg-red-[5-9]00|text-red-[5-9]00/);
    });
  });

  describe("Due Date Display", () => {
    it("should format due date in a human-readable way", () => {
      render(<TaskCard task={mockTask} />);

      // Should show month abbreviation and day
      expect(screen.getByText(/Feb 1/)).toBeInTheDocument();
    });

    it("should show overdue indicator with calm styling", () => {
      const overdueTask = {
        ...mockTask,
        dueDate: new Date("2025-01-01"), // Past date
      };
      render(<TaskCard task={overdueTask} />);

      // Should indicate overdue but not in harsh red
      const dueDateElement = screen.getByText(/Jan 1/);
      const className = dueDateElement.className;

      // Should avoid aggressive red
      expect(className).not.toMatch(/bg-red-[5-9]00|text-red-[5-9]00/);
    });

    it("should show due soon indicator for tasks due within 3 days", () => {
      const tomorrow = new Date();
      tomorrow.setDate(tomorrow.getDate() + 1);

      const soonTask = {
        ...mockTask,
        dueDate: tomorrow,
      };

      const { container } = render(<TaskCard task={soonTask} />);

      // Should have some visual indicator (checked via data attribute or aria label)
      expect(container).toBeInTheDocument();
    });
  });

  describe("Drag and Drop", () => {
    it("should be draggable", () => {
      const { container } = render(<TaskCard task={mockTask} />);

      const card = container.querySelector('[role="article"]');
      expect(card).toBeInTheDocument();
    });

    it("should have appropriate cursor style for dragging", () => {
      const { container } = render(<TaskCard task={mockTask} />);

      const card = container.querySelector('[role="article"]');
      const className = card?.className || "";

      // Should have cursor-grab or cursor-move
      expect(className).toMatch(/cursor-(grab|move)/);
    });
  });

  describe("Accessibility", () => {
    it("should have accessible task card", () => {
      render(<TaskCard task={mockTask} />);

      const card = screen.getByRole("article");
      expect(card).toBeInTheDocument();
    });

    it("should have semantic heading for task title", () => {
      render(<TaskCard task={mockTask} />);

      const heading = screen.getByRole("heading", { level: 4 });
      expect(heading).toHaveTextContent("Complete project documentation");
    });

    it("should provide aria-label for due date icon", () => {
      const { container } = render(<TaskCard task={mockTask} />);

      // Icons should have proper aria labels
      const icons = container.querySelectorAll("svg");
      icons.forEach((icon) => {
        const ariaLabel = icon.getAttribute("aria-label");
        const parentAriaLabel = icon.parentElement?.getAttribute("aria-label");

        // Either the icon or its parent should have an aria-label
        expect(ariaLabel || parentAriaLabel || icon.getAttribute("aria-hidden")).toBeTruthy();
      });
    });
  });

  describe("PDA-Friendly Design", () => {
    it("should not use harsh or demanding language", () => {
      const { container } = render(<TaskCard task={mockTask} />);

      const allText = container.textContent?.toLowerCase() || "";

      // Should avoid demanding words
      expect(allText).not.toMatch(/must|required|urgent|critical|error|alert/);
    });

    it("should use gentle visual design", () => {
      const { container } = render(<TaskCard task={mockTask} />);

      const card = container.querySelector('[role="article"]');
      const className = card?.className || "";

      // Should have rounded corners and soft shadows
      expect(className).toMatch(/rounded/);
    });
  });

  describe("Compact Mode", () => {
    it("should handle missing description gracefully", () => {
      const taskWithoutDescription = { ...mockTask, description: null };
      render(<TaskCard task={taskWithoutDescription} />);

      expect(screen.getByText("Complete project documentation")).toBeInTheDocument();
      // Description should not be rendered
    });
  });

  describe("Error Handling", () => {
    it("should handle task with minimal data", () => {
      const minimalTask: Task = {
        id: "task-minimal",
        title: "Minimal task",
        description: null,
        status: TaskStatus.NOT_STARTED,
        priority: TaskPriority.MEDIUM,
        dueDate: null,
        assigneeId: null,
        creatorId: "user-1",
        workspaceId: "workspace-1",
        projectId: null,
        parentId: null,
        sortOrder: 0,
        metadata: {},
        completedAt: null,
        createdAt: new Date(),
        updatedAt: new Date(),
      };

      render(<TaskCard task={minimalTask} />);

      expect(screen.getByText("Minimal task")).toBeInTheDocument();
    });
  });

  describe("Visual Feedback", () => {
    it("should show hover state with subtle transition", () => {
      const { container } = render(<TaskCard task={mockTask} />);

      const card = container.querySelector('[role="article"]');
      const className = card?.className || "";

      // Should have hover transition
      expect(className).toMatch(/transition|hover:/);
    });
  });
});
