import { useMemo } from "react";
import { Loader2 } from "lucide-react";
import {
  groupPhasesByDependencyLevel,
  type DependencyEdge,
} from "@codewalk-district/shared";
import { StatusBadge } from "@/components/StatusBadge";
import { mapEntityStatus, type StatusVariant } from "@/components/StatusDot";
import { cn } from "@/lib/utils";
import type { PhaseData } from "./ExecutionContext";

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

interface PhaseGraphProps {
  phases: PhaseData[];
  dependencyEdges: DependencyEdge[];
  taskCountsByPhase: Record<string, { complete: number; total: number }>;
  activePhaseId: string | null;
  onSelectPhase: (id: string) => void;
  detailAgentByPhase: Map<string, { status: string }>;
  allDisplayIndices: Map<string, number>;
}

// ---------------------------------------------------------------------------
// 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",
};

const selectedRingClasses: Record<StatusVariant, string> = {
  active:  "ring-status-active-dot/40",
  success: "ring-status-success-dot/40",
  warning: "ring-status-warning-dot/40",
  error:   "ring-status-error-dot/40",
  neutral: "ring-border",
  urgent:  "ring-status-urgent-dot/40",
};

// ---------------------------------------------------------------------------
// PhaseGraph — vertical execution graph ordered by dependency depth
// ---------------------------------------------------------------------------

export function PhaseGraph({
  phases,
  dependencyEdges,
  taskCountsByPhase,
  activePhaseId,
  onSelectPhase,
  detailAgentByPhase,
  allDisplayIndices,
}: PhaseGraphProps) {
  const columns = useMemo(
    () => groupPhasesByDependencyLevel(phases, dependencyEdges),
    [phases, dependencyEdges],
  );

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

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

        // Connector coloring: green if all prior layers completed
        const prevAllCompleted =
          colIdx > 0 &&
          columns
            .slice(0, colIdx)
            .every((c) =>
              c.phases.every(
                (p) => mapEntityStatus(p.status) === "success",
              ),
            );

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

            {isParallel ? (
              <div className="relative rounded-lg border border-dashed border-border/60 px-1 pb-1 pt-3.5">
                <span className="absolute -top-2.5 left-2.5 rounded-sm bg-background px-1.5 py-px text-[9px] font-semibold uppercase tracking-[0.12em] text-muted-foreground/50">
                  Parallel &middot; {col.phases.length}
                </span>
                <div className="space-y-0.5">
                  {col.phases.map((phase) => (
                    <GraphNode
                      key={phase.id}
                      phase={phase}
                      taskCount={
                        taskCountsByPhase[phase.id] ?? {
                          complete: 0,
                          total: 0,
                        }
                      }
                      isSelected={phase.id === activePhaseId}
                      onClick={() => onSelectPhase(phase.id)}
                      detailAgent={
                        detailAgentByPhase.get(phase.id) ?? null
                      }
                      displayIndex={
                        allDisplayIndices.get(phase.id) ?? 0
                      }
                    />
                  ))}
                </div>
              </div>
            ) : (
              <GraphNode
                phase={col.phases[0]}
                taskCount={
                  taskCountsByPhase[col.phases[0].id] ?? {
                    complete: 0,
                    total: 0,
                  }
                }
                isSelected={col.phases[0].id === activePhaseId}
                onClick={() => onSelectPhase(col.phases[0].id)}
                detailAgent={
                  detailAgentByPhase.get(col.phases[0].id) ?? null
                }
                displayIndex={
                  allDisplayIndices.get(col.phases[0].id) ?? 0
                }
              />
            )}
          </div>
        );
      })}
    </div>
  );
}

// ---------------------------------------------------------------------------
// GraphNode — single phase in the execution graph
// ---------------------------------------------------------------------------

function GraphNode({
  phase,
  taskCount,
  isSelected,
  onClick,
  detailAgent,
  displayIndex,
}: {
  phase: PhaseData;
  taskCount: { complete: number; total: number };
  isSelected: boolean;
  onClick: () => void;
  detailAgent: { status: string } | null;
  displayIndex: number;
}) {
  const variant = mapEntityStatus(phase.status);
  const isDetailing =
    detailAgent?.status === "running" ||
    detailAgent?.status === "waiting_for_input";
  const detailDone = detailAgent?.status === "idle";

  return (
    <button
      className={cn(
        "group flex w-full items-start gap-2.5 rounded-md px-2 py-2 text-left transition-all",
        isSelected
          ? cn("bg-accent shadow-xs ring-1", selectedRingClasses[variant])
          : "hover:bg-accent/40",
      )}
      onClick={onClick}
    >
      {/* Rail dot */}
      <div
        className={cn(
          "mt-[5px] h-2.5 w-2.5 shrink-0 rounded-full transition-all",
          railDotClasses[variant],
          variant === "active" && "animate-status-pulse",
          isSelected && "scale-125",
        )}
      />

      {/* Content */}
      <div className="min-w-0 flex-1">
        <div className="flex items-center gap-1.5">
          <span className="font-mono text-[10px] font-bold leading-none text-muted-foreground/60">
            {displayIndex}
          </span>
          <span className="min-w-0 flex-1 truncate text-[13px] font-medium leading-tight">
            {phase.name}
          </span>
          <StatusBadge
            status={phase.status}
            className="shrink-0 text-[9px]"
          />
        </div>
        <div className="mt-0.5 pl-[18px] text-[11px] text-muted-foreground">
          {isDetailing ? (
            <span className="flex items-center gap-1 text-status-active-fg">
              <Loader2 className="h-3 w-3 animate-spin" />
              Detailing…
            </span>
          ) : detailDone && taskCount.total === 0 ? (
            <span className="text-status-warning-fg">Review changes</span>
          ) : taskCount.total === 0 ? (
            <span>No tasks</span>
          ) : (
            <span>
              {taskCount.complete}/{taskCount.total} tasks
            </span>
          )}
        </div>
      </div>
    </button>
  );
}

// ---------------------------------------------------------------------------
// LayerConnector — vertical line between dependency layers
// ---------------------------------------------------------------------------

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