import { useNavigate } from "react-router";
import type { ChainStep, ContractPhase } from "../../lib/api";
import { PhaseProgressBarCompact } from "../contracts/PhaseProgressBar";

interface StepDiagramProps {
  steps: ChainStep[];
}

const statusColors: Record<string, { border: string; dot: string; bg: string; glow: string }> = {
  pending: {
    border: "border-[#444]",
    dot: "bg-[#555]",
    bg: "bg-[rgba(40,40,50,0.6)]",
    glow: "",
  },
  running: {
    border: "border-yellow-400/60",
    dot: "bg-yellow-400",
    bg: "bg-[rgba(80,70,20,0.3)]",
    glow: "shadow-[0_0_8px_rgba(250,204,21,0.15)]",
  },
  evaluating: {
    border: "border-blue-400/60",
    dot: "bg-blue-400",
    bg: "bg-[rgba(20,50,80,0.3)]",
    glow: "shadow-[0_0_8px_rgba(96,165,250,0.15)]",
  },
  passed: {
    border: "border-green-400/60",
    dot: "bg-green-400",
    bg: "bg-[rgba(20,60,30,0.3)]",
    glow: "",
  },
  failed: {
    border: "border-red-400/60",
    dot: "bg-red-400",
    bg: "bg-[rgba(60,20,20,0.3)]",
    glow: "",
  },
};

const statusLabels: Record<string, string> = {
  pending: "Pending",
  running: "Running",
  evaluating: "Evaluating",
  passed: "Passed",
  failed: "Failed",
};

/**
 * Assign depth to each step via topological sort based on dependsOn UUIDs.
 */
function assignDepths(steps: ChainStep[]): Map<string, number> {
  const depths = new Map<string, number>();
  const stepMap = new Map(steps.map((s) => [s.id, s]));

  function getDepth(id: string): number {
    if (depths.has(id)) return depths.get(id)!;
    const step = stepMap.get(id);
    if (!step || !step.dependsOn || step.dependsOn.length === 0) {
      depths.set(id, 0);
      return 0;
    }
    const maxParent = Math.max(
      ...step.dependsOn.map((depId) => getDepth(depId))
    );
    const d = maxParent + 1;
    depths.set(id, d);
    return d;
  }

  for (const step of steps) {
    getDepth(step.id);
  }

  return depths;
}

function StepCard({ step }: { step: ChainStep }) {
  const navigate = useNavigate();
  const colors = statusColors[step.status] || statusColors.pending;
  const summary = step.contractSummary;
  const hasContract = !!step.contractId;

  return (
    <div
      className={`
        border ${colors.border} ${colors.bg} ${colors.glow}
        p-3 w-[220px] transition-all duration-200
        ${hasContract ? "cursor-pointer hover:brightness-125" : ""}
      `}
      onClick={() => {
        if (hasContract) navigate(`/contracts/${step.contractId}`);
      }}
      title={hasContract ? "View contract" : undefined}
    >
      {/* Status header */}
      <div className="flex items-center justify-between mb-2">
        <div className="flex items-center gap-2 min-w-0 flex-1">
          <div className={`w-2 h-2 rounded-full ${colors.dot} shrink-0 ${
            step.status === "running" ? "animate-pulse" : ""
          }`} />
          <span className="font-mono text-[11px] text-[#dbe7ff] truncate font-medium">
            {step.name}
          </span>
        </div>
        <span className={`font-mono text-[9px] uppercase tracking-wider shrink-0 ml-2 ${
          step.status === "passed" ? "text-green-400" :
          step.status === "failed" ? "text-red-400" :
          step.status === "running" ? "text-yellow-400" :
          step.status === "evaluating" ? "text-blue-400" :
          "text-[#555]"
        }`}>
          {statusLabels[step.status] || step.status}
        </span>
      </div>

      {/* Description */}
      {step.description && (
        <p className="font-mono text-[10px] text-[#7788aa] mb-2 line-clamp-2 leading-relaxed">
          {step.description}
        </p>
      )}

      {/* Contract progress */}
      {summary && (
        <div className="border-t border-[rgba(117,170,252,0.1)] pt-2 mt-1">
          <div className="mb-1.5">
            <PhaseProgressBarCompact
              currentPhase={summary.phase as ContractPhase}
            />
          </div>
          <div className="flex items-center gap-3 font-mono text-[9px]">
            <span className="text-[#7788aa]">
              {summary.tasksDone}/{summary.taskCount} tasks
            </span>
            {summary.tasksRunning > 0 && (
              <span className="text-yellow-400">
                {summary.tasksRunning} running
              </span>
            )}
            {summary.tasksFailed > 0 && (
              <span className="text-red-400">
                {summary.tasksFailed} failed
              </span>
            )}
          </div>
        </div>
      )}

      {/* Contract link arrow */}
      {hasContract && !summary && (
        <div className="border-t border-[rgba(117,170,252,0.1)] pt-1.5 mt-1">
          <span className="font-mono text-[9px] text-[#75aafc]">
            view contract &rarr;
          </span>
        </div>
      )}
    </div>
  );
}

/** Vertical connector between levels */
function LevelConnector({ count }: { count: number }) {
  return (
    <div className="flex justify-center py-1">
      <div className="flex items-center gap-3">
        {Array.from({ length: count }).map((_, i) => (
          <div key={i} className="flex flex-col items-center">
            <div className="w-px h-4 bg-[rgba(117,170,252,0.25)]" />
            <div className="text-[rgba(117,170,252,0.4)] text-[10px] leading-none">&darr;</div>
            <div className="w-px h-4 bg-[rgba(117,170,252,0.25)]" />
          </div>
        ))}
      </div>
    </div>
  );
}

export function StepDiagram({ steps }: StepDiagramProps) {
  if (steps.length === 0) {
    return (
      <p className="font-mono text-xs text-[#7788aa]">No steps to display.</p>
    );
  }

  const depths = assignDepths(steps);
  const maxDepth = Math.max(...Array.from(depths.values()));

  // Group steps by depth level
  const levels: ChainStep[][] = [];
  for (let d = 0; d <= maxDepth; d++) {
    levels.push(
      steps
        .filter((s) => depths.get(s.id) === d)
        .sort((a, b) => a.orderIndex - b.orderIndex)
    );
  }

  // Compute overall progress
  const passedCount = steps.filter(s => s.status === "passed").length;
  const failedCount = steps.filter(s => s.status === "failed").length;
  const runningCount = steps.filter(s => s.status === "running" || s.status === "evaluating").length;

  return (
    <div>
      {/* Progress summary */}
      <div className="flex items-center gap-4 mb-4 font-mono text-[10px]">
        <span className="text-[#7788aa]">
          {levels.length} level{levels.length !== 1 ? "s" : ""} &middot; {steps.length} step{steps.length !== 1 ? "s" : ""}
        </span>
        {passedCount > 0 && (
          <span className="text-green-400">{passedCount} passed</span>
        )}
        {runningCount > 0 && (
          <span className="text-yellow-400">{runningCount} active</span>
        )}
        {failedCount > 0 && (
          <span className="text-red-400">{failedCount} failed</span>
        )}
        <div className="flex-1 h-1 bg-[rgba(117,170,252,0.1)] rounded-full overflow-hidden">
          <div
            className="h-full bg-green-400/60 rounded-full transition-all duration-500"
            style={{ width: `${(passedCount / steps.length) * 100}%` }}
          />
        </div>
        <span className="text-[#7788aa]">
          {Math.round((passedCount / steps.length) * 100)}%
        </span>
      </div>

      {/* Chain flow */}
      <div className="flex flex-col items-center">
        {levels.map((level, li) => (
          <div key={li}>
            {/* Level label */}
            {levels.length > 1 && (
              <div className="flex justify-center mb-2">
                <span className="font-mono text-[9px] text-[#555] uppercase tracking-widest px-2 py-0.5 border border-[rgba(117,170,252,0.1)] bg-[rgba(0,0,0,0.3)]">
                  {li === 0 ? "Start" : li === maxDepth ? "Final" : `Level ${li}`}
                </span>
              </div>
            )}

            {/* Steps at this level */}
            <div className="flex items-start justify-center gap-3 flex-wrap">
              {level.map((step) => (
                <StepCard key={step.id} step={step} />
              ))}
            </div>

            {/* Connector to next level */}
            {li < maxDepth && (
              <LevelConnector count={Math.min(level.length, 3)} />
            )}
          </div>
        ))}
      </div>
    </div>
  );
}
