"use client";

import { Calendar, User } from "lucide-react";
import {
  BaseBoxShapeUtil,
  HTMLContainer,
  T,
  type TLBaseShape,
  toDomPrecision,
} from "tldraw";

import { cn } from "@/lib/utils";

export type TaskCardShape = TLBaseShape<
  "task-card",
  {
    w: number;
    h: number;
    objectId: string;
    title: string;
    status: "open" | "in_progress" | "done" | "closed";
    priority: string;
    assignees: string;
    dueDate: string;
  }
>;

declare module "@tldraw/tlschema" {
  interface TLGlobalShapePropsMap {
    "task-card": TaskCardShape["props"];
  }
}

const STATUS_DOT: Record<TaskCardShape["props"]["status"], string> = {
  open: "bg-zinc-400 dark:bg-zinc-500",
  in_progress: "bg-blue-500 dark:bg-blue-400",
  done: "bg-emerald-500 dark:bg-emerald-400",
  closed: "bg-slate-500 dark:bg-slate-400",
};

function priorityClass(priority: string): string {
  const p = priority.toLowerCase();
  if (p.includes("high")) return "bg-red-500/15 text-red-700 ring-1 ring-red-500/30 dark:text-red-300";
  if (p.includes("low")) return "bg-emerald-500/15 text-emerald-700 ring-1 ring-emerald-500/30 dark:text-emerald-300";
  return "bg-amber-500/15 text-amber-800 ring-1 ring-amber-500/30 dark:text-amber-200";
}

function initialsFromName(name: string): string {
  const parts = name.trim().split(/\s+/).filter(Boolean);
  if (parts.length === 0) return "?";
  if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
  return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
}

function TaskCardBody({ shape }: { shape: TaskCardShape }) {
  const { title, status, priority, assignees, dueDate } = shape.props;
  const names = assignees
    .split(",")
    .map((s) => s.trim())
    .filter(Boolean)
    .slice(0, 2);

  return (
    <HTMLContainer>
      <div
        className={cn(
          "flex h-full w-full flex-col overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--card-foreground))] shadow-sm",
          "ring-1 ring-[hsl(var(--primary)/0.12)]",
        )}
        style={{ fontSize: "11px", lineHeight: 1.35 }}
      >
        <div className="flex min-h-0 flex-1 flex-col px-2.5 pb-1.5 pt-2">
          <div className="flex min-w-0 items-start gap-2">
            <span
              className={cn("mt-1.5 size-2 shrink-0 rounded-full", STATUS_DOT[status])}
              title={status.replace("_", " ")}
              aria-hidden
            />
            <div className="min-w-0 flex-1 font-semibold leading-tight tracking-tight text-[13px]">
              {title || "Untitled task"}
            </div>
          </div>

          <div className="mt-2 flex flex-wrap items-center gap-1.5">
            <span
              className={cn(
                "inline-flex max-w-full truncate rounded px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide",
                priorityClass(priority),
              )}
            >
              {priority || "—"}
            </span>
            {names.length > 0 ? (
              <div className="flex items-center gap-0.5">
                {names.map((name, i) => (
                  <span
                    key={`${name}-${i}`}
                    className="flex size-6 items-center justify-center rounded-full bg-[hsl(var(--muted))] text-[9px] font-semibold text-[hsl(var(--muted-foreground))] ring-1 ring-[hsl(var(--border))]"
                    title={name}
                  >
                    {initialsFromName(name)}
                  </span>
                ))}
              </div>
            ) : (
              <span className="inline-flex items-center gap-0.5 text-[10px] text-[hsl(var(--muted-foreground))]">
                <User className="size-3 shrink-0 opacity-70" aria-hidden />
                <span>Unassigned</span>
              </span>
            )}
          </div>

          {dueDate ? (
            <div className="mt-auto flex items-center gap-1 pt-2 text-[10px] text-[hsl(var(--muted-foreground))]">
              <Calendar className="size-3 shrink-0 opacity-80" aria-hidden />
              <span className="truncate">{dueDate}</span>
            </div>
          ) : (
            <div className="mt-auto pt-2 text-[10px] text-[hsl(var(--muted-foreground)/0.6)]">No due date</div>
          )}
        </div>

        <div className="border-t border-[hsl(var(--border)/0.65)] bg-[hsl(var(--muted)/0.35)] px-2.5 py-1 text-[9px] font-medium uppercase tracking-wider text-[hsl(var(--muted-foreground))]">
          Task
        </div>
      </div>
    </HTMLContainer>
  );
}

export class TaskCardShapeUtil extends BaseBoxShapeUtil<TaskCardShape> {
  static override type = "task-card";

  static override props = {
    w: T.number,
    h: T.number,
    objectId: T.string,
    title: T.string,
    status: T.literalEnum("open", "in_progress", "done", "closed"),
    priority: T.string,
    assignees: T.string,
    dueDate: T.string,
  };

  override getDefaultProps(): TaskCardShape["props"] {
    return {
      w: 240,
      h: 160,
      objectId: "",
      title: "Task",
      status: "open",
      priority: "Medium",
      assignees: "",
      dueDate: "",
    };
  }

  override getAriaDescriptor(shape: TaskCardShape) {
    return shape.props.title;
  }

  override component(shape: TaskCardShape) {
    return <TaskCardBody shape={shape} />;
  }

  override indicator(shape: TaskCardShape) {
    return (
      <rect
        width={toDomPrecision(shape.props.w)}
        height={toDomPrecision(shape.props.h)}
        rx={10}
        ry={10}
      />
    );
  }

  override useLegacyIndicator() {
    return false;
  }

  override getIndicatorPath(shape: TaskCardShape) {
    const p = new Path2D();
    p.roundRect(0, 0, shape.props.w, shape.props.h, 10);
    return p;
  }
}
