/**
 * Modelica / TIL-style medium colours for diagram wires and connectors.
 *
 * Convention (TIL Media + common refrigeration Modelica libraries):
 *   - Refrigerant (VLE) … green
 *   - Water / brine / glycol … blue
 *   - Air / gas …………… yellow / amber
 *
 * Buildings/MSL do not hard-code medium colours on connectors; TIL and most
 * HVAC libraries do — we follow that engineering diagram practice.
 */

import { isSecondaryPort } from "./componentMeta";
import type { EntropykNodeData } from "./configBuilder";
import type { Node } from "@xyflow/react";

export type MediaKind = "refrigerant" | "water" | "air" | "unknown";

/** Stroke / connector fill colours (TIL-like). */
export const MEDIA_COLOR: Record<MediaKind, string> = {
  refrigerant: "#2e7d32", // green — two-phase / VLE
  water: "#1565c0", // blue — liquid HTF (Modelica connector blue)
  air: "#f9a825", // amber/yellow — gas / moist air
  unknown: "#36475a",
};

export const MEDIA_LABEL: Record<MediaKind, string> = {
  refrigerant: "Frigorigène",
  water: "Eau / brine",
  air: "Air",
  unknown: "Autre",
};

const AIR_TYPES = new Set([
  "AirSource",
  "AirSink",
  "Fan",
  "FinCoilCondenser",
  "AirCooledCondenser",
  "MchxCondenserCoil",
]);

const WATER_TYPES = new Set([
  "BrineSource",
  "BrineSink",
  "Pump",
  "FreeCoolingExchanger",
  "WaterPipe",
  "PipeWater",
]);

const AIR_PIPE_TYPES = new Set(["AirDuct", "PipeAir"]);

const REFRIGERANT_TYPES = new Set([
  "RefrigerantSource",
  "RefrigerantSink",
  "IsentropicCompressor",
  "Compressor",
  "ScrewEconomizerCompressor",
  "CentrifugalCompressor",
  "IsenthalpicExpansionValve",
  "ExpansionValve",
  "CapillaryTube",
  "ReversingValve",
  "BypassValve",
  "FloodedEvaporator",
  "BphxEvaporator",
  "BphxCondenser",
  "Condenser",
  "Evaporator",
  "CondenserCoil",
  "EvaporatorCoil",
  "Drum",
  "Pipe",
  "RefrigerantPipe",
  "FlowSplitter",
  "FlowMerger",
]);

/** Map a fluid name string to a medium kind. */
export function classifyFluidName(raw: string | undefined | null): MediaKind | null {
  if (!raw) return null;
  const f = String(raw).trim().toLowerCase();
  if (!f) return null;
  if (
    f === "air" ||
    f === "moistair" ||
    f === "moist_air" ||
    f.startsWith("air")
  ) {
    return "air";
  }
  if (
    f === "water" ||
    f === "meg" ||
    f === "mpg" ||
    f.includes("glycol") ||
    f.includes("brine") ||
    f === "incompressiblewater"
  ) {
    return "water";
  }
  // R134a, R410A, CO2, ammonia, …
  if (
    f.startsWith("r") ||
    f === "co2" ||
    f === "r744" ||
    f.includes("ammonia") ||
    f === "nh3" ||
    f === "propane" ||
    f === "r290"
  ) {
    return "refrigerant";
  }
  return null;
}

type PortHost =
  | Node<EntropykNodeData>
  | { data: EntropykNodeData }
  | undefined;

/**
 * Infer the medium on a specific port of a component (Modelica Medium package).
 */
export function mediaForPort(
  node: PortHost,
  port: string | null | undefined,
): MediaKind {
  if (!node) return "unknown";
  const type = node.data.type;
  const params = node.data.params ?? {};
  const p = port ?? "";

  if (type === "SaturatedController" || type === "Placeholder") return "unknown";

  // Explicit 4-port HX fluid ids
  if (p === "hot_inlet" || p === "hot_outlet") {
    return classifyFluidName(String(params.hot_fluid_id ?? params.hot_fluid ?? "")) ?? "water";
  }
  if (p === "cold_inlet" || p === "cold_outlet") {
    return classifyFluidName(String(params.cold_fluid_id ?? params.cold_fluid ?? "")) ?? "air";
  }

  // Secondary / HTF side of refrigerant HX
  if (isSecondaryPort(p)) {
    if (AIR_TYPES.has(type)) return "air";
    const sec = classifyFluidName(
      String(params.secondary_fluid ?? params.fluid ?? ""),
    );
    if (sec) return sec;
    // Flooded / BPHX / generic condenser-evaporator → water loop by default
    return "water";
  }

  // Dedicated pipe / duct components (palette types)
  if (AIR_PIPE_TYPES.has(type)) return "air";
  if (type === "WaterPipe" || type === "PipeWater") return "water";
  if (type === "RefrigerantPipe") return "refrigerant";
  if (type === "Pipe") {
    return classifyFluidName(String(params.fluid ?? "")) ?? "refrigerant";
  }

  // Whole-component media (sources, fans, pumps)
  if (AIR_TYPES.has(type) && !isSecondaryPort(p) && type !== "FinCoilCondenser" && type !== "AirCooledCondenser" && type !== "MchxCondenserCoil") {
    return "air";
  }
  if (type === "Fan") return "air";
  if (WATER_TYPES.has(type)) {
    return classifyFluidName(String(params.fluid ?? "")) ?? "water";
  }
  if (type === "AirSource" || type === "AirSink") return "air";
  if (type === "BrineSource" || type === "BrineSink") return "water";

  // Air-cooled coils: primary ports are refrigerant, secondary already handled
  if (AIR_TYPES.has(type)) return "refrigerant";

  if (REFRIGERANT_TYPES.has(type)) {
    return classifyFluidName(String(params.fluid ?? params.refrigerant ?? "")) ?? "refrigerant";
  }

  // HeatExchanger primary-style ports without hot_/cold_ prefix
  if (type === "HeatExchanger") {
    return classifyFluidName(String(params.hot_fluid_id ?? "")) ?? "water";
  }

  return "refrigerant";
}

/** Edge medium: prefer the upstream (source) port, fall back to target. */
export function mediaForEdge(
  source: Node<EntropykNodeData> | undefined,
  sourceHandle: string | null | undefined,
  target: Node<EntropykNodeData> | undefined,
  targetHandle: string | null | undefined,
): MediaKind {
  const a = mediaForPort(source, sourceHandle);
  if (a !== "unknown") return a;
  return mediaForPort(target, targetHandle);
}

export function mediaColor(kind: MediaKind): string {
  return MEDIA_COLOR[kind];
}
