"use client";

import {
  AlertTriangle,
  Check,
  ChevronDown,
  Clipboard,
  Factory,
  Network,
  RadioTower,
} from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { ToggleGroup } from "radix-ui";

import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { BELT_TYPES, type BeltId, type BeltStackSize } from "@/app/lib/belts";
import type {
  BlueprintBlockSettings,
  ProductionGeometryProps,
} from "@/app/lib/blueprint-contract";
import { QUALITIES, iconFor } from "@/app/lib/factorio-data";
import { localizedName } from "@/app/lib/i18n";
import type { QualityId } from "@/app/lib/types";
import {
  FieldLabel,
  formatNumber,
} from "@/app/components/calculator-widgets";
import { FactorioIcon } from "@/app/components/factorio-icon";
import {
  blueprintNodes,
  encodeBlueprintString,
  generateBlueprintPlan,
} from "./generator";
import { BlueprintPreview } from "./blueprint-preview";
import { generateChainBlueprintPlan } from "./chain-generator";
import { SUBSTATION_REACH } from "./power-grid";

/* Shared generator for the static website and the portable Windows build. */
export const BLUEPRINT_GENERATOR_ENABLED = true;

async function copyText(value: string) {
  if (navigator.clipboard?.writeText) {
    await navigator.clipboard.writeText(value);
    return;
  }
  const field = document.createElement("textarea");
  field.value = value;
  field.style.position = "fixed";
  field.style.opacity = "0";
  document.body.append(field);
  field.select();
  const copied = document.execCommand("copy");
  field.remove();
  if (!copied) throw new Error("Clipboard unavailable. Select and copy the blueprint string below.");
}

export function ProductionGeometry({
  input,
  result,
  logistics,
  logisticsSettings,
  chain,
  settings,
  onChange,
  locale,
}: ProductionGeometryProps) {
  const labels =
    locale === "de"
      ? {
          title: "Blueprint-Generator",
          development: "Blueprint-Export",
          targetGroup: "Blueprint-Ziel",
          combine: "Produktionskette einbeziehen",
          combineHint: "Dieses Produkt mit seinen aktivierten Teilprozessen. Gleiche Konfigurationen innerhalb der Kette werden mit addiertem Bedarf zusammengeführt.",
          chain: "Produktionskette",
          shared: "Teilzweige",
          encoding: "Blueprint wird aktualisiert …",
          targetHint: "Produkt und Teilprozess für diesen Block",
          transportGroup: "Item-Transport",
          transportHint: "Bandtyp, Stapelgröße und Kapazitätsreserve",
          coverageGroup: "Versorgung & Kachelung",
          coverageHint: "Strom, Logistiknetz und Platzierungsraster",
          orientation: "Blueprint-Ausrichtung",
          orientationHint: "Horizontal verlaufen Band- und Rohrtrassen waagerecht, vertikal senkrecht. Maschinen und Anschlüsse drehen sich mit.",
          alignment: "Produktion im Substation-Raster ausrichten",
          alignmentHint: "Mitte bezieht sich auf das Substation-Raster. Die vier Maschinenkanten werden an dessen inneren Kanten ausgerichtet. Feste Roboports begrenzen die Produktion an ihrer zugewandten Kante, wenn sie im Weg stehen. In/Out-Symbole beeinflussen die Ausrichtung nicht.",
          alignmentDisabled: "Für die Ausrichtung das Substation-Netz aktivieren.",
          horizontal: "Horizontal",
          vertical: "Vertikal",
          horizontalPosition: "Horizontale Position",
          verticalPosition: "Vertikale Position",
          left: "Links",
          center: "Mitte",
          right: "Rechts",
          top: "Oben",
          bottom: "Unten",
          process: "Produkt / Teilprozess",
          belt: "Gewünschtes Transportband",
          stack: "Bandstapel",
          autoUpgrade: "Überlastete Bänder automatisch passend hochstufen",
          powerFirst: "Vier-Ecken-Netz auf voller Substation-Reichweite",
          powerHint: "Tiles Abstand · Rand-Substations werden beim Kacheln geteilt",
          substationQuality: "Substation-Qualität",
          roboports: "Lückenlose Roboport-Abdeckung",
          north: "Roboports fest über den Substations",
          south: "Roboports fest unter den Substations",
          snap: "Am Blueprint-Raster einrasten",
          machines: "Maschinen / Block",
          repeats: "Blöcke gesamt",
          entities: "Blueprint-Entitäten",
          grid: "Kachelraster",
          copy: "Blueprint kopieren",
          copied: "Kopiert",
          string: "Kopierbaren Blueprint-String anzeigen",
          rawFallback:
            "Der kopierbare String wird bei jeder relevanten Änderung neu erzeugt.",
          previewNote:
            "Kachelgenauer Entitätsplan mit symbolischen Maschinen, Bändern und Rohrverbindungen. Gestrichelte Leitungen verlaufen unterirdisch.",
          validation:
            "Die Vorschau kann stellenweise falsch dargestellt werden. Bitte probiere den Blueprint-String direkt im Spiel aus.",
          effective: "In der Vorschau",
          completeCoverage: "Roboport-Abdeckung vollständig",
          incompleteCoverage: "Roboport-Abdeckung prüfen",
          beaconCoverage: "Beacon-Abdeckung vollständig",
          beaconCoverageCheck: "Beacon-Abdeckung prüfen",
          powerCoverage: "Substation-Rahmen vollständig",
          powerCoverageCheck: "Substation-Rahmen prüfen",
        }
      : {
          title: "Blueprint generator",
          development: "Blueprint export",
          targetGroup: "Blueprint target",
          combine: "Include production chain",
          combineHint: "This product and its enabled sub-processes. Matching configurations within this chain are merged with their combined demand.",
          chain: "Production chain",
          shared: "branches",
          encoding: "Updating blueprint …",
          targetHint: "Product and sub-process for this block",
          transportGroup: "Item transport",
          transportHint: "Belt type, stack size and capacity reserve",
          coverageGroup: "Supply & tiling",
          coverageHint: "Power, logistics network and placement grid",
          orientation: "Blueprint orientation",
          orientationHint: "Horizontal places belt and pipe lanes across the preview; vertical places them up and down. Machines and connections rotate together.",
          alignment: "Align production within the Substation grid",
          alignmentHint: "Center refers to the Substation grid. The four machine edges align with its inner edges. Where fixed Roboports are in the way, their facing edge limits production. In/Out markers do not affect alignment.",
          alignmentDisabled: "Enable the Substation network to choose an alignment.",
          horizontal: "Horizontal",
          vertical: "Vertical",
          horizontalPosition: "Horizontal position",
          verticalPosition: "Vertical position",
          left: "Left",
          center: "Center",
          right: "Right",
          top: "Top",
          bottom: "Bottom",
          process: "Product / sub-process",
          belt: "Requested transport belt",
          stack: "Belt stack size",
          autoUpgrade: "Automatically upgrade overloaded belts in the preview",
          powerFirst: "Four-corner network at full Substation reach",
          powerHint: "tile spacing · boundary Substations are shared when tiled",
          substationQuality: "Substation quality",
          roboports: "Complete Roboport coverage",
          north: "Roboports fixed above Substations",
          south: "Roboports fixed below Substations",
          snap: "Snap blueprint to grid",
          machines: "Machines / block",
          repeats: "Total blocks",
          entities: "Blueprint entities",
          grid: "Tile grid",
          copy: "Copy blueprint",
          copied: "Copied",
          string: "Show copyable blueprint string",
          rawFallback:
            "The copyable string is regenerated after every relevant change.",
          previewNote:
            "Tile-aligned entity plan with symbolic machines, belts and pipe connections. Dashed lines run underground.",
          validation:
            "The preview may display some details incorrectly. Please try the blueprint string directly in the game.",
          effective: "Used in preview",
          completeCoverage: "Roboport coverage complete",
          incompleteCoverage: "Check Roboport coverage",
          beaconCoverage: "Beacon coverage complete",
          beaconCoverageCheck: "Check Beacon coverage",
          powerCoverage: "Substation frame complete",
          powerCoverageCheck: "Check Substation frame",
        };
  const nodes = useMemo(
    () => blueprintNodes(input, result, logistics, logisticsSettings, chain),
    [chain, input, logistics, logisticsSettings, result],
  );
  const selectedNode =
    nodes.find((node) => node.key === settings.nodeKey) ?? nodes[0];
  const { plan, planError } = useMemo(() => {
    try {
      return {
        plan: settings.includeChain
          ? generateChainBlueprintPlan({ input, result, chain, logisticsSettings, logistics }, settings, locale)
          : generateBlueprintPlan(selectedNode, settings, locale),
        planError: "",
      };
    } catch (error) {
      return {
        plan: generateBlueprintPlan(selectedNode, { ...settings, substationPriority: false, roboportCoverage: false }, locale),
        planError: error instanceof Error ? error.message : String(error),
      };
    }
  }, [locale, selectedNode, settings, input, result, chain, logistics, logisticsSettings]);
  const [encodedBlueprint, setEncodedBlueprint] = useState({
    source: "",
    value: "",
    error: "",
  });
  const [copiedSource, setCopiedSource] = useState("");
  const copied = copiedSource === plan.blueprintJson;
  const [panelOpen, setPanelOpen] = useState(true);

  useEffect(() => {
    if (planError) return;
    let active = true;
    encodeBlueprintString(plan.blueprintJson)
      .then((value) => {
        if (active) setEncodedBlueprint({ source: plan.blueprintJson, value, error: "" });
      })
      .catch((error) => {
        if (active) setEncodedBlueprint({ source: plan.blueprintJson, value: "", error: String(error) });
      });
    return () => {
      active = false;
    };
  }, [plan.blueprintJson, planError]);
  const blueprintString =
    !planError && encodedBlueprint.source === plan.blueprintJson
      ? encodedBlueprint.value
      : "";

  function patch(next: Partial<BlueprintBlockSettings>) {
    onChange({ ...settings, ...next });
  }

  const effectiveBelts = [...new Set(
    plan.beltLoads.map((entry) => entry.load.effectiveBeltId),
  )];

  return (
    <details
      open={panelOpen}
      onToggle={(event) => setPanelOpen(event.currentTarget.open)}
      className="blueprint-panel group overflow-hidden rounded-xl border-2 border-[#69c5df]/32 bg-[#0d0f10]"
    >
      <summary className="flex cursor-pointer list-none flex-wrap items-center justify-between gap-3 px-4 py-3.5 transition hover:bg-white/[.025]">
        <div className="flex min-w-0 items-start gap-3">
          <span className="flex size-10 shrink-0 items-center justify-center rounded-lg border border-[#69c5df]/35 bg-[#69c5df]/10 text-[#a8e8f7]">
            <Factory className="size-5" />
          </span>
          <div className="min-w-0">
            <p className="text-base font-semibold text-[#a8e8f7]">{labels.title}</p>
            <p className="font-mono text-xs uppercase tracking-wider text-[#f7a72d]">
              {labels.development}
            </p>
          </div>
        </div>
        <span className="flex items-center gap-2">
          <span className="rounded-md border border-white/8 bg-[#17191b] px-2.5 py-1 font-mono text-xs text-zinc-400">
            {settings.includeChain ? `${labels.chain} · ${localizedName(input.product.id, locale, input.product.type)}` : localizedName(selectedNode.input.machine.id, locale, "entity")}
          </span>
          <ChevronDown className="details-chevron size-4 shrink-0 text-[#69c5df] transition-transform" />
        </span>
      </summary>

      <div className="blueprint-panel-body border-t border-white/7 p-4">

      <div className="grid gap-3 xl:grid-cols-2">
        <section className="rounded-xl border border-[#69c5df]/22 bg-[#121517] p-3 xl:col-span-2">
          <div className="mb-3">
            <p className="text-sm font-semibold text-[#a8e8f7]">{labels.targetGroup}</p>
            <p className="text-xs text-zinc-600">{labels.targetHint}</p>
          </div>
          <label className="mb-3 flex min-h-14 cursor-pointer items-center justify-between gap-4 rounded-lg border border-[#69c5df]/30 bg-[#69c5df]/6 px-3 py-2">
            <span><strong className="block text-sm text-[#b7dbe8]">{labels.combine}</strong><span className="mt-1 block text-sm leading-relaxed text-zinc-400">{labels.combineHint}</span></span>
            <input type="checkbox" checked={settings.includeChain === true} onChange={(event) => patch({ includeChain: event.target.checked })} />
          </label>
          <div>
            <FieldLabel>{labels.process}</FieldLabel>
          <Select
            disabled={settings.includeChain === true}
            value={settings.includeChain ? nodes[0].key : selectedNode.key}
            onValueChange={(nodeKey) => patch({ nodeKey })}
          >
            <SelectTrigger className="h-11 w-full border-white/10 bg-[#17191b] text-zinc-100">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              {nodes.map((node) => (
                <SelectItem key={node.key} value={node.key}>
                  <span className="flex items-center gap-2">
                    <FactorioIcon src={node.input.product.icon} alt="" size="sm" />
                    <span>{"↳ ".repeat(Math.min(3, node.depth))}</span>
                    {localizedName(
                      node.input.product.id,
                      locale,
                      node.input.product.type,
                    )}
                    <span className="text-zinc-600">
                      · {formatNumber(node.result.machinesToBuild, locale, 0)} ×
                    </span>
                  </span>
                </SelectItem>
              ))}
            </SelectContent>
            </Select>
          </div>
        </section>

        <section className="rounded-xl border border-[#74b768]/22 bg-[#121517] p-3">
          <div className="mb-3">
            <p className="text-sm font-semibold text-[#b9e2b3]">{labels.transportGroup}</p>
            <p className="text-xs text-zinc-600">{labels.transportHint}</p>
          </div>
          <div className="grid gap-3 sm:grid-cols-2">
        <div>
          <FieldLabel>{labels.belt}</FieldLabel>
          <Select
            value={settings.beltId}
            onValueChange={(beltId) => patch({ beltId: beltId as BeltId })}
          >
            <SelectTrigger
              className={`h-11 w-full bg-[#17191b] text-zinc-100 ${
                plan.requestedBeltOverloaded
                  ? "border-2 border-[#e65d4f] shadow-[0_0_18px_rgba(230,93,79,.18)]"
                  : "border-white/10"
              }`}
            >
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              {BELT_TYPES.map((belt) => (
                <SelectItem key={belt.id} value={belt.id}>
                  <span className="flex items-center gap-2">
                    <FactorioIcon src={iconFor(belt.id)} alt="" size="sm" />
                    {localizedName(belt.id, locale, "entity")}
                  </span>
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
        <div>
          <FieldLabel>{labels.stack}</FieldLabel>
          <Select
            value={String(settings.beltStackSize)}
            onValueChange={(value) =>
              patch({ beltStackSize: Number(value) as BeltStackSize })
            }
          >
            <SelectTrigger className="h-11 w-full border-white/10 bg-[#17191b] text-zinc-100">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              {[1, 2, 3, 4].map((stack) => (
                <SelectItem key={stack} value={String(stack)}>
                  {stack} ×
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
        <label className="flex min-h-11 cursor-pointer items-center justify-between gap-3 rounded-lg border border-white/8 bg-[#17191b] px-3 py-2 text-sm sm:col-span-2">
          <span>{labels.autoUpgrade}</span>
          <input
            type="checkbox"
            checked={settings.autoUpgradeBelt}
            onChange={(event) => patch({ autoUpgradeBelt: event.target.checked })}
          />
        </label>
          </div>
        </section>

        <section className="rounded-xl border border-[#f7a72d]/22 bg-[#121517] p-3">
          <div className="mb-3">
            <p className="text-sm font-semibold text-[#e7c987]">{labels.coverageGroup}</p>
            <p className="text-xs text-zinc-600">{labels.coverageHint}</p>
          </div>
          <div className="grid gap-3 sm:grid-cols-2">
        <label className="flex min-h-11 cursor-pointer items-center justify-between gap-3 rounded-lg border border-[#f7a72d]/24 bg-[#f7a72d]/6 px-3 py-2 text-sm">
          <span className="flex items-center gap-2">
            <RadioTower className="size-4 text-[#f7a72d]" />
            {labels.powerFirst}
          </span>
          <input
            type="checkbox"
            checked={settings.substationPriority}
            onChange={(event) =>
              patch({
                substationPriority: event.target.checked,
                ...(!event.target.checked ? { roboportCoverage: false } : {}),
              })
            }
          />
        </label>
        <div>
          <FieldLabel>{labels.substationQuality}</FieldLabel>
          {settings.substationPriority ? <p className="mb-2 text-xs leading-relaxed text-zinc-400">{SUBSTATION_REACH[settings.substationQuality]} {labels.powerHint}</p> : null}
          <Select
            disabled={!settings.substationPriority}
            value={settings.substationQuality}
            onValueChange={(quality) =>
              patch({ substationQuality: quality as QualityId })
            }
          >
            <SelectTrigger className="h-11 w-full border-white/10 bg-[#17191b] text-zinc-100">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              {QUALITIES.map((quality) => (
                <SelectItem key={quality.id} value={quality.id}>
                  <span className="flex items-center gap-2">
                    <FactorioIcon src={quality.icon} alt="" size="sm" />
                    {localizedName(quality.id, locale, "quality")}
                  </span>
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
        <div className="contents">
          <label className="flex min-h-11 cursor-pointer items-center justify-between gap-3 rounded-lg border border-[#69c5df]/24 bg-[#69c5df]/6 px-3 py-2 text-sm">
            <span className="flex items-center gap-2">
              <Network className="size-4 text-[#69c5df]" />
              {labels.roboports}
            </span>
            <input
              type="checkbox"
              checked={settings.roboportCoverage}
              onChange={(event) =>
                patch({
                  roboportCoverage: event.target.checked,
                  ...(event.target.checked ? { substationPriority: true } : {}),
                })
              }
            />
          </label>
          <Select
            disabled={!settings.roboportCoverage}
            value={settings.roboportSide}
            onValueChange={(side) =>
              patch({ roboportSide: side as "north" | "south" })
            }
          >
            <SelectTrigger className="h-11 w-full border-white/10 bg-[#17191b] text-zinc-100">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="north">{labels.north}</SelectItem>
              <SelectItem value="south">{labels.south}</SelectItem>
            </SelectContent>
          </Select>
        </div>
        <label className="flex min-h-11 cursor-pointer items-center justify-between gap-3 rounded-lg border border-white/8 bg-[#17191b] px-3 py-2 text-sm sm:col-span-2">
          <span>{labels.snap}</span>
          <input
            type="checkbox"
            checked={settings.snapToGrid !== false}
            onChange={(event) => patch({ snapToGrid: event.target.checked })}
          />
        </label>
          </div>
        </section>
      </div>

      <section className="mt-3 rounded-xl border border-[#69c5df]/22 bg-[#121517] p-3">
        <p className="text-sm font-semibold text-[#a8e8f7]">{labels.orientation}</p>
        <p className="mt-1 text-sm leading-relaxed text-zinc-400">{labels.orientationHint}</p>
        <ToggleGroup.Root type="single" value={settings.orientation ?? "horizontal"} aria-label={labels.orientation}
          onValueChange={(value) => { if (value === "horizontal" || value === "vertical") patch({ orientation: value }); }}
          className="mt-3 grid grid-cols-2 gap-1 rounded-lg border border-white/10 bg-[#0d0f10] p-1">
          {(["horizontal", "vertical"] as const).map((value) => <ToggleGroup.Item key={value} value={value}
            className="min-h-10 rounded-md px-2 text-sm text-zinc-400 transition hover:bg-white/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#69c5df] data-[state=on]:bg-[#69c5df]/18 data-[state=on]:text-[#c0effa]">
            {labels[value]}
          </ToggleGroup.Item>)}
        </ToggleGroup.Root>
      </section>

      <section className="mt-3 rounded-xl border border-[#69c5df]/22 bg-[#121517] p-3">
        <p className="text-sm font-semibold text-[#a8e8f7]">{labels.alignment}</p>
        <p className="mt-1 text-sm leading-relaxed text-zinc-400">{settings.substationPriority ? labels.alignmentHint : labels.alignmentDisabled}</p>
        <div className="mt-3 grid gap-3 sm:grid-cols-2">
          {([
            ["horizontalAlignment", labels.horizontalPosition, ["left", "center", "right"]],
            ["verticalAlignment", labels.verticalPosition, ["top", "center", "bottom"]],
          ] as const).map(([key, label, options]) => <div key={key}>
            <FieldLabel>{label}</FieldLabel>
            <ToggleGroup.Root type="single" value={settings[key] ?? "center"}
              disabled={!settings.substationPriority} aria-label={label}
              onValueChange={(value) => { if (value) patch({ [key]: value }); }}
              className="grid grid-cols-3 gap-1 rounded-lg border border-white/10 bg-[#0d0f10] p-1">
              {options.map((value) => <ToggleGroup.Item key={value} value={value} aria-label={`${label}: ${labels[value]}`}
                className="min-h-10 rounded-md px-2 text-sm text-zinc-400 transition hover:bg-white/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#69c5df] disabled:cursor-not-allowed disabled:opacity-40 data-[state=on]:bg-[#69c5df]/18 data-[state=on]:text-[#c0effa]">
                {labels[value]}
              </ToggleGroup.Item>)}
            </ToggleGroup.Root>
          </div>)}
        </div>
      </section>

      {planError ? <div role="alert" className="notice-warning mt-3">{planError}</div> : <>
      {plan.chainProcesses ? <div className="mt-3 grid gap-2 sm:grid-cols-2">
        {plan.chainProcesses.map((process, index) => <div key={index} className="flex items-center gap-2 rounded-lg border border-white/8 bg-[#121517] px-3 py-2 text-sm">
          <FactorioIcon src={iconFor(process.machineId)} alt="" size="sm" />
          <span className="min-w-0 flex-1">{localizedName(process.productId, locale)}<span className="block text-sm text-zinc-400">{localizedName(process.recipeId, locale, "recipe")}{process.sources > 1 ? ` · ${process.sources} ${labels.shared}` : ""}</span></span>
          <strong className="font-mono">{process.machines} ×</strong>
        </div>)}
      </div> : null}
      <div className="mt-3 grid gap-2 sm:grid-cols-2 xl:grid-cols-4">
        {[
          [labels.machines, plan.machineCountInBlock],
          [labels.repeats, plan.repeatCount],
          [labels.entities, plan.entityCount],
          [labels.grid, `${plan.grid.x} × ${plan.grid.y}`],
        ].map(([label, value]) => (
          <div key={String(label)} className="rounded-lg border border-white/8 bg-[#17191b] px-3 py-2">
            <span className="block text-xs uppercase tracking-wider text-zinc-600">
              {label}
            </span>
            <strong className="font-mono text-sm text-zinc-100">{value}</strong>
          </div>
        ))}
      </div>

      {effectiveBelts.length || settings.substationPriority || plan.layout.uniqueBeacons ? (
        <div className="mt-3 flex flex-wrap items-center gap-2 rounded-lg border border-[#74b768]/24 bg-[#74b768]/6 px-3 py-2 text-sm">
          <span className="text-zinc-500">{labels.effective}:</span>
          {effectiveBelts.map((beltId) => (
            <span key={beltId} className="flex items-center gap-1.5 text-[#b9e2b3]">
              <FactorioIcon src={iconFor(beltId)} alt="" size="sm" />
              {localizedName(beltId, locale, "entity")}
            </span>
          ))}
          {plan.layout.uniqueBeacons > 0 ? (
            <span className={plan.beaconCoverageComplete ? "text-[#b9e2b3]" : "text-[#f2b0aa]"}>
              · {plan.beaconCoverageComplete ? labels.beaconCoverage : labels.beaconCoverageCheck}
            </span>
          ) : null}
          {settings.substationPriority ? (
            <span className={plan.substationCoverageComplete ? "text-[#b9e2b3]" : "text-[#f2b0aa]"}>
              · {plan.substationCoverageComplete ? labels.powerCoverage : labels.powerCoverageCheck}
            </span>
          ) : null}
          {settings.roboportCoverage ? (
            <span className={plan.roboportCoverageComplete ? "text-[#b9e2b3]" : "text-[#f2b0aa]"}>
              · {plan.roboportCoverageComplete ? labels.completeCoverage : labels.incompleteCoverage}
            </span>
          ) : null}
        </div>
      ) : null}

      <div className="mt-4">
        <BlueprintPreview
          layout={plan.layout}
          grid={plan.grid}
          machine={selectedNode.input.machine}
          locale={locale}
          title={settings.includeChain ? `${labels.chain} · ${localizedName(input.product.id, locale, input.product.type)}` : `${labels.title} · ${localizedName(
            selectedNode.input.product.id,
            locale,
            selectedNode.input.product.type,
          )}`}
          subtitle={labels.previewNote}
        />
      </div>

      {plan.warnings.length ? (
        <div className="mt-3 space-y-2">
          {plan.warnings.map((warning, index) => (
            <div key={`${warning.code}:${index}`} className="notice-warning">
              <AlertTriangle className="size-4 shrink-0" />
              <span>{warning.message}</span>
            </div>
          ))}
        </div>
      ) : null}

      <div className="mt-3 rounded-lg border border-[#e5a12b]/24 bg-[#e5a12b]/6 px-3 py-2 text-sm leading-relaxed text-[#e7c987]">
        {labels.validation}
      </div>

      <div className="mt-3 flex flex-wrap gap-2">
        <button
          type="button"
          disabled={!blueprintString}
          onClick={async () => {
            try {
              await copyText(blueprintString);
              setCopiedSource(plan.blueprintJson);
              window.setTimeout(() => setCopiedSource(""), 1800);
            } catch (error) {
              setEncodedBlueprint({ source: plan.blueprintJson, value: blueprintString, error: String(error) });
            }
          }}
          className="disabled:cursor-wait disabled:opacity-50 inline-flex min-h-10 items-center gap-2 rounded-lg border border-[#74b768]/40 bg-[#74b768]/10 px-4 py-2 text-sm font-semibold text-[#b9e2b3] transition hover:bg-[#74b768]/16"
        >
          {copied ? <Check className="size-4" /> : <Clipboard className="size-4" />}
          {copied ? labels.copied : blueprintString ? labels.copy : labels.encoding}
        </button>
      </div>
      {encodedBlueprint.source === plan.blueprintJson && encodedBlueprint.error ? <p role="alert" className="notice-warning mt-2">{encodedBlueprint.error}</p> : null}
      <details className="mt-3 overflow-hidden rounded-lg border border-white/8 bg-[#111315]">
        <summary className="flex cursor-pointer items-center justify-between gap-3 p-3 text-sm text-zinc-300">
          <span>{labels.string}</span>
          <ChevronDown className="details-chevron size-4 text-zinc-500 transition" />
        </summary>
        <div className="border-t border-white/7 p-3">
          <textarea
            readOnly
            value={blueprintString}
            placeholder={labels.encoding}
            onFocus={(event) => event.currentTarget.select()}
            className="min-h-36 w-full resize-y rounded-md border border-white/10 bg-[#080909] p-3 font-mono text-xs leading-relaxed text-zinc-300 outline-none focus:border-[#69c5df]/50"
            aria-label={labels.string}
          />
          <p className="mt-2 text-xs text-zinc-600">{labels.rawFallback}</p>
        </div>
      </details>
      </>}
      </div>
    </details>
  );
}
