import { useMemo } from "react";
import { X } from "lucide-react";
import {
  groupPhasesByDependencyLevel,
  type DependencyEdge,
} from "@codewalk-district/shared";
import { Badge } from "@/components/ui/badge";
import { StatusBadge } from "@/components/StatusBadge";
import { mapEntityStatus, type StatusVariant } from "@/components/StatusDot";
import { getCategoryConfig } from "@/lib/category";
import { cn } from "@/lib/utils";
import type { SerializedTask } from "@/components/TaskRow";

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

interface TaskGraphProps {
  tasks: SerializedTask[];
  /** Raw edges: { taskId, dependsOn: string[] } */
  taskDepsRaw: Array<{ taskId: string; dependsOn: string[] }>;
  /** Count of incomplete dependencies per task */
  blockedByCountMap: Map<string, number>;
  /** Agent name per task (empty Map when not wired up) */
  agentNameMap: Map<string, string>;
  onClickTask: (taskId: string) => void;
  onDeleteTask?: (taskId: string) => void;
  /** Hide category badge and priority — use in compact contexts like the pipeline */
  compact?: boolean;
}

// ---------------------------------------------------------------------------
// Styling maps
// ---------------------------------------------------------------------------

const railDotClasses: Record<StatusVariant, string> = {
  active:  "bg-status-active-dot",
  success: "bg-status-success-dot",
  warning: "bg-status-warning-dot",
  error:   "bg-status-error-dot",
  neutral: "bg-muted-foreground/30",
  urgent:  "bg-status-urgent-dot",
};

// ---------------------------------------------------------------------------
// TaskGraph — vertical execution graph for tasks within a phase
// ---------------------------------------------------------------------------

export function TaskGraph({
  tasks,
  taskDepsRaw,
  blockedByCountMap,
  agentNameMap,
  onClickTask,
  onDeleteTask,
  compact = false,
}: TaskGraphProps) {
  // Flatten task dep edges to DependencyEdge format for reuse of groupPhasesByDependencyLevel
  const columns = useMemo(() => {
    const edges: DependencyEdge[] = [];
    for (const raw of taskDepsRaw) {
      for (const depId of raw.dependsOn) {
        edges.push({ phaseId: raw.taskId, dependsOnPhaseId: depId });
      }
    }
    // groupPhasesByDependencyLevel accepts anything with { id, createdAt }
    return groupPhasesByDependencyLevel(tasks, edges);
  }, [tasks, taskDepsRaw]);

  if (columns.length === 0) return null;

  return (
    <div className="relative">
      {columns.map((col, colIdx) => {
        const isParallel = col.phases.length > 1;
        const isFirst = colIdx === 0;

        const prevAllCompleted =
          colIdx > 0 &&
          columns
            .slice(0, colIdx)
            .every((c) =>
              c.phases.every(
                (t) => mapEntityStatus(t.status) === "success",
              ),
            );

        return (
          <div
            key={col.depth}
            style={{
              animation: "graph-layer-enter 0.25s ease-out both",
              animationDelay: `${colIdx * 30}ms`,
            }}
          >
            {!isFirst && (
              <TaskLayerConnector completed={prevAllCompleted} />
            )}

            {isParallel ? (
              <div className="relative rounded-lg border border-dashed border-border px-0.5 pb-0.5 pt-3">
                <span className="absolute -top-2 left-2 rounded-sm bg-background px-1.5 py-px text-[8px] font-semibold uppercase tracking-[0.12em] text-muted-foreground/70">
                  Parallel &middot; {col.phases.length}
                </span>
                <div className="space-y-px">
                  {col.phases.map((task) => (
                    <TaskNode
                      key={task.id}
                      task={task}
                      blockedByCount={blockedByCountMap.get(task.id) ?? 0}
                      agentName={agentNameMap.get(task.id)}
                      onClick={() => onClickTask(task.id)}
                      onDelete={
                        onDeleteTask
                          ? () => onDeleteTask(task.id)
                          : undefined
                      }
                      compact={compact}
                    />
                  ))}
                </div>
              </div>
            ) : (
              <TaskNode
                task={col.phases[0]}
                blockedByCount={blockedByCountMap.get(col.phases[0].id) ?? 0}
                agentName={agentNameMap.get(col.phases[0].id)}
                onClick={() => onClickTask(col.phases[0].id)}
                onDelete={
                  onDeleteTask
                    ? () => onDeleteTask(col.phases[0].id)
                    : undefined
                }
                compact={compact}
              />
            )}
          </div>
        );
      })}
    </div>
  );
}

// ---------------------------------------------------------------------------
// TaskNode — single task in the execution graph
// ---------------------------------------------------------------------------

function TaskNode({
  task,
  blockedByCount,
  agentName,
  onClick,
  onDelete,
  compact = false,
}: {
  task: SerializedTask;
  blockedByCount: number;
  agentName?: string;
  onClick: () => void;
  onDelete?: () => void;
  compact?: boolean;
}) {
  const variant = mapEntityStatus(task.status);
  const catConfig = getCategoryConfig(task.category);

  const priorityColor =
    task.priority === "high"
      ? "text-status-error-fg"
      : task.priority === "medium"
        ? "text-status-warning-fg"
        : null;

  const hasSecondLine =
    !compact && (true /* category badge always shows */ || priorityColor || agentName || blockedByCount > 0);

  return (
    <div
      className={cn(
        "group flex w-full cursor-pointer gap-2 rounded-md px-2 text-left transition-all hover:bg-accent/50",
        compact ? "py-1" : "py-1.5",
      )}
      onClick={onClick}
    >
      {/* Rail dot — aligned to first text line */}
      <div
        className={cn(
          "mt-[5px] h-2 w-2 shrink-0 rounded-full transition-all",
          railDotClasses[variant],
          variant === "active" && "animate-status-pulse",
        )}
      />

      {/* Content */}
      <div className="min-w-0 flex-1">
        {/* Line 1: name + status + blocked count (compact) + delete */}
        <div className="flex items-center gap-2">
          <span className="min-w-0 flex-1 truncate text-[13px]">
            {task.name}
          </span>
          {compact && blockedByCount > 0 && (
            <span className="shrink-0 text-[10px] text-muted-foreground">
              {blockedByCount} dep{blockedByCount === 1 ? "" : "s"}
            </span>
          )}
          <StatusBadge
            status={task.status}
            className="shrink-0 text-[9px]"
          />
          {onDelete && (
            <button
              className="shrink-0 rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:text-destructive group-hover:opacity-100"
              title="Delete task (Shift+click to skip confirmation)"
              onClick={(e) => {
                e.stopPropagation();
                if (e.shiftKey || window.confirm(`Delete "${task.name}"?`)) {
                  onDelete();
                }
              }}
            >
              <X className="h-3.5 w-3.5" />
            </button>
          )}
        </div>

        {/* Line 2: category + priority + agent + blocked count (full mode only) */}
        {hasSecondLine && (
          <div className="mt-0.5 flex items-center gap-1.5">
            <Badge variant={catConfig.variant} size="xs">
              {catConfig.label}
            </Badge>
            {priorityColor && (
              <span className={cn("text-[10px] font-medium capitalize", priorityColor)}>
                {task.priority}
              </span>
            )}
            {agentName && (
              <span className="truncate text-[10px] text-muted-foreground">
                {agentName}
              </span>
            )}
            {blockedByCount > 0 && (
              <span className="text-[10px] text-muted-foreground">
                blocked by {blockedByCount}
              </span>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// TaskLayerConnector
// ---------------------------------------------------------------------------

function TaskLayerConnector({ completed }: { completed: boolean }) {
  return (
    <div className="flex justify-center py-px">
      <div
        className={cn(
          "h-2.5 w-[2px] rounded-full",
          completed ? "bg-status-success-dot/50" : "bg-border",
        )}
      />
    </div>
  );
}
