import { useState } from "react";
import { ChevronRight, ChevronDown } from "lucide-react";
import type { ExplainNode, ExplainResult } from "@/types";

function getCostColor(cost: number, maxCost: number): string {
  if (maxCost === 0) return "var(--success)";
  const ratio = cost / maxCost;
  if (ratio < 0.33) return "var(--success)";
  if (ratio < 0.66) return "var(--warning)";
  return "var(--destructive)";
}

function getMaxCost(node: ExplainNode): number {
  let max = node["Total Cost"];
  if (node.Plans) {
    for (const child of node.Plans) {
      max = Math.max(max, getMaxCost(child));
    }
  }
  return max;
}

function ExplainNodeRow({
  node,
  maxCost,
  depth,
}: {
  node: ExplainNode;
  maxCost: number;
  depth: number;
}) {
  const [expanded, setExpanded] = useState(true);
  const hasChildren = node.Plans && node.Plans.length > 0;
  const costColor = getCostColor(node["Total Cost"], maxCost);
  const costPercent = maxCost > 0 ? (node["Total Cost"] / maxCost) * 100 : 0;

  return (
    <div>
      <button
        className="flex w-full items-start gap-1.5 px-2 py-1.5 text-left text-xs hover:bg-accent"
        style={{ paddingLeft: depth * 20 + 8 }}
        onClick={() => setExpanded(!expanded)}
      >
        {hasChildren ? (
          expanded ? (
            <ChevronDown className="mt-0.5 h-3 w-3 shrink-0 text-muted-foreground" />
          ) : (
            <ChevronRight className="mt-0.5 h-3 w-3 shrink-0 text-muted-foreground" />
          )
        ) : (
          <span className="w-3 shrink-0" />
        )}
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2">
            <span className="font-semibold" style={{ color: costColor }}>
              {node["Node Type"]}
            </span>
            {node["Relation Name"] && (
              <span className="text-muted-foreground">
                on {node["Schema"] ? `${node["Schema"]}.` : ""}
                {node["Relation Name"]}
                {node["Alias"] && node["Alias"] !== node["Relation Name"]
                  ? ` (${node["Alias"]})`
                  : ""}
              </span>
            )}
            {node["Join Type"] && (
              <span className="text-muted-foreground">
                ({node["Join Type"]})
              </span>
            )}
            {node["Index Name"] && (
              <span className="text-muted-foreground">
                using {node["Index Name"]}
              </span>
            )}
          </div>
          <div className="mt-0.5 flex items-center gap-3 text-muted-foreground">
            <span>cost: {node["Total Cost"].toFixed(2)}</span>
            {node["Actual Total Time"] != null && (
              <span>time: {node["Actual Total Time"].toFixed(3)} ms</span>
            )}
            {node["Actual Rows"] != null && (
              <span>rows: {node["Actual Rows"]}</span>
            )}
            {node["Actual Loops"] != null && node["Actual Loops"] > 1 && (
              <span>loops: {node["Actual Loops"]}</span>
            )}
            {(node["Shared Hit Blocks"] != null ||
              node["Shared Read Blocks"] != null) && (
              <span>
                buffers: hit={node["Shared Hit Blocks"] ?? 0} read=
                {node["Shared Read Blocks"] ?? 0}
              </span>
            )}
          </div>
          <div className="mt-1 h-1.5 w-full overflow-hidden rounded-full bg-muted">
            <div
              className="h-full rounded-full"
              style={{
                width: `${costPercent}%`,
                backgroundColor: costColor,
              }}
            />
          </div>
        </div>
      </button>
      {expanded &&
        hasChildren &&
        node.Plans!.map((child, i) => (
          <ExplainNodeRow
            key={i}
            node={child}
            maxCost={maxCost}
            depth={depth + 1}
          />
        ))}
    </div>
  );
}

interface Props {
  data: ExplainResult;
}

export function ExplainView({ data }: Props) {
  const maxCost = getMaxCost(data.Plan);

  return (
    <div className="flex h-full flex-col overflow-hidden">
      <div className="flex items-center gap-4 border-b px-3 py-2 text-xs">
        <span className="font-semibold">Summary</span>
        <span>
          Execution:{" "}
          <span className="font-mono">{data["Execution Time"].toFixed(3)} ms</span>
        </span>
        <span>
          Planning:{" "}
          <span className="font-mono">{data["Planning Time"].toFixed(3)} ms</span>
        </span>
        <span>
          Total Cost:{" "}
          <span className="font-mono">{data.Plan["Total Cost"].toFixed(2)}</span>
        </span>
      </div>
      <div className="min-h-0 flex-1 overflow-y-auto">
        <ExplainNodeRow node={data.Plan} maxCost={maxCost} depth={0} />
      </div>
    </div>
  );
}
