import { describe, expect, it } from "vitest";
import type { Edge, Node } from "@xyflow/react";
import type { EntropykNodeData } from "./configBuilder";
import {
  findNearestEdge,
  planEdgeInsert,
  pipeMediaKind,
  validatePipeOnEdge,
} from "./edgeInsert";

function node(
  id: string,
  type: string,
  name: string,
  x: number,
  y: number,
): Node<EntropykNodeData> {
  return {
    id,
    type: "entropykNode",
    position: { x, y },
    width: 100,
    height: 60,
    data: { type, name, circuit: 0, rotation: 0, params: {} },
  };
}

describe("edgeInsert", () => {
  it("classifies pipe media", () => {
    expect(pipeMediaKind("WaterPipe")).toBe("water");
    expect(pipeMediaKind("AirDuct")).toBe("air");
    expect(pipeMediaKind("RefrigerantPipe")).toBe("refrigerant");
  });

  it("finds nearest edge and plans A→pipe→B splice", () => {
    const nodes = [
      node("a", "BrineSource", "evap_water_in", 0, 0),
      node("b", "FloodedEvaporator", "evap", 200, 0),
    ];
    const edges: Edge[] = [
      {
        id: "e1",
        source: "a",
        target: "b",
        sourceHandle: "outlet",
        targetHandle: "secondary_inlet",
      },
    ];
    const hit = findNearestEdge({ x: 100, y: 30 }, nodes, edges, {
      preferMedia: "water",
    });
    expect(hit?.edge.id).toBe("e1");
    expect(hit?.media).toBe("water");

    const ok = validatePipeOnEdge("WaterPipe", { fluid: "Water" }, hit!.edge, nodes);
    expect(ok.ok).toBe(true);

    const plan = planEdgeInsert({
      type: "WaterPipe",
      id: "pipe1",
      name: "water_pipe_1",
      position: hit!.midpoint,
      params: { fluid: "Water", length_m: 5 },
      edge: hit!.edge,
      sourceCenter: hit!.sourceCenter,
      targetCenter: hit!.targetCenter,
    });
    expect(plan.edgeIdToRemove).toBe("e1");
    expect(plan.node.data.rotation).toBe(0); // left → right
    expect(plan.edgesToAdd).toHaveLength(2);
    expect(plan.edgesToAdd[0]).toMatchObject({
      source: "a",
      target: "pipe1",
      targetHandle: "inlet",
    });
    expect(plan.edgesToAdd[1]).toMatchObject({
      source: "pipe1",
      sourceHandle: "outlet",
      target: "b",
    });
  });

  it("orients pipe 180° when flow is right-to-left", () => {
    const plan = planEdgeInsert({
      type: "RefrigerantPipe",
      id: "p2",
      name: "ref_1",
      position: { x: 0, y: 0 },
      params: {},
      edge: {
        id: "e",
        source: "right",
        target: "left",
        sourceHandle: "outlet",
        targetHandle: "inlet",
      },
      sourceCenter: { x: 300, y: 100 },
      targetCenter: { x: 100, y: 100 },
    });
    expect(plan.node.data.rotation).toBe(180);
  });

  it("rejects water pipe on refrigerant edge", () => {
    const nodes = [
      node("c", "IsentropicCompressor", "comp", 0, 0),
      node("d", "Condenser", "cond", 200, 0),
    ];
    const edge: Edge = {
      id: "e2",
      source: "c",
      target: "d",
      sourceHandle: "outlet",
      targetHandle: "inlet",
    };
    const check = validatePipeOnEdge("WaterPipe", { fluid: "Water" }, edge, nodes);
    expect(check.ok).toBe(false);
  });
});
