"use client";

import { useState, useRef, useCallback, useEffect } from "react";
import {
  Copy,
  Check,
  Hash,
  Type,
  Percent,
  Ruler,
  Zap,
  Wand2,
  Building2,
  FileDown,
  ScanText,
  CaseUpper,
  Palette,
  Upload,
  Receipt,
  Layers,
  ArrowUp,
  ArrowDown,
  Unlock,
  PenTool,
  Maximize2,
} from "lucide-react";
import { Button } from "@/shared/components/ui/button";
import { Input } from "@/shared/components/ui/input";
import { Label } from "@/shared/components/ui/label";
import { Textarea } from "@/shared/components/ui/textarea";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
} from "@/shared/components/ui/card";
import {
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
} from "@/shared/components/ui/tabs";

function CopyButton({ text }: { text: string }) {
  const [copied, setCopied] = useState(false);
  const handleCopy = async () => {
    try {
      await navigator.clipboard.writeText(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 1500);
    } catch {
      /* silent */
    }
  };
  return (
    <Button
      variant="ghost"
      size="icon"
      className="h-7 w-7"
      onClick={handleCopy}
      disabled={!text}
    >
      {copied ? (
        <Check className="h-3.5 w-3.5 text-green-500" />
      ) : (
        <Copy className="h-3.5 w-3.5" />
      )}
    </Button>
  );
}

function TextCaseConverter() {
  const [input, setInput] = useState("");
  const upper = input.toUpperCase();
  const lower = input.toLowerCase();
  const title = input.replace(/\b\w/g, (c) => c.toUpperCase());
  const sentence = input.charAt(0).toUpperCase() + input.slice(1).toLowerCase();

  return (
    <div className="space-y-3">
      <div>
        <Label>Text sursă</Label>
        <Textarea
          value={input}
          onChange={(e) => setInput(e.target.value)}
          rows={3}
          className="mt-1"
          placeholder="Introdu text..."
        />
      </div>
      {[
        { label: "UPPERCASE", value: upper },
        { label: "lowercase", value: lower },
        { label: "Title Case", value: title },
        { label: "Sentence case", value: sentence },
      ].map(({ label, value }) => (
        <div key={label} className="flex items-center gap-2">
          <code className="flex-1 truncate rounded border bg-muted/30 px-2 py-1 text-xs">
            {value || "—"}
          </code>
          <span className="w-24 text-xs text-muted-foreground">{label}</span>
          <CopyButton text={value} />
        </div>
      ))}
    </div>
  );
}

function CharacterCounter() {
  const [input, setInput] = useState("");
  const chars = input.length;
  const charsNoSpaces = input.replace(/\s/g, "").length;
  const words = input.trim() ? input.trim().split(/\s+/).length : 0;
  const lines = input ? input.split("\n").length : 0;

  return (
    <div className="space-y-3">
      <div>
        <Label>Text</Label>
        <Textarea
          value={input}
          onChange={(e) => setInput(e.target.value)}
          rows={5}
          className="mt-1"
          placeholder="Introdu text..."
        />
      </div>
      <div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
        <Card>
          <CardContent className="p-3">
            <p className="text-xs text-muted-foreground">Caractere</p>
            <p className="text-xl font-bold">{chars}</p>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="p-3">
            <p className="text-xs text-muted-foreground">Fără spații</p>
            <p className="text-xl font-bold">{charsNoSpaces}</p>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="p-3">
            <p className="text-xs text-muted-foreground">Cuvinte</p>
            <p className="text-xl font-bold">{words}</p>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="p-3">
            <p className="text-xs text-muted-foreground">Linii</p>
            <p className="text-xl font-bold">{lines}</p>
          </CardContent>
        </Card>
      </div>
    </div>
  );
}

function PercentageCalculator() {
  const [value, setValue] = useState("");
  const [total, setTotal] = useState("");
  const [percent, setPercent] = useState("");

  const v = parseFloat(value);
  const t = parseFloat(total);
  const p = parseFloat(percent);

  const pctOfTotal =
    !isNaN(v) && !isNaN(t) && t !== 0 ? ((v / t) * 100).toFixed(2) : "—";
  const valFromPct = !isNaN(p) && !isNaN(t) ? ((p / 100) * t).toFixed(2) : "—";

  return (
    <div className="space-y-4">
      <div className="grid gap-3 sm:grid-cols-3">
        <div>
          <Label>Valoare</Label>
          <Input
            type="number"
            value={value}
            onChange={(e) => setValue(e.target.value)}
            className="mt-1"
          />
        </div>
        <div>
          <Label>Total</Label>
          <Input
            type="number"
            value={total}
            onChange={(e) => setTotal(e.target.value)}
            className="mt-1"
          />
        </div>
        <div>
          <Label>Procent</Label>
          <Input
            type="number"
            value={percent}
            onChange={(e) => setPercent(e.target.value)}
            className="mt-1"
          />
        </div>
      </div>
      <div className="space-y-2 rounded-md border bg-muted/30 p-3 text-sm">
        <p>
          <strong>{value || "?"}</strong> din <strong>{total || "?"}</strong> ={" "}
          <strong>{pctOfTotal}%</strong>
        </p>
        <p>
          <strong>{percent || "?"}%</strong> din <strong>{total || "?"}</strong>{" "}
          = <strong>{valFromPct}</strong>
        </p>
      </div>
    </div>
  );
}

const TVA_PRESETS = [5, 9, 19, 21];

function TvaCalculator() {
  const [tvaRate, setTvaRate] = useState(19);
  const [customRate, setCustomRate] = useState("");
  const [amount, setAmount] = useState("");
  const [mode, setMode] = useState<"add" | "extract">("add");

  const effectiveRate =
    customRate !== "" ? parseFloat(customRate) || tvaRate : tvaRate;
  const val = parseFloat(amount);
  const tvaMultiplier = effectiveRate / 100;

  const cuTva = !isNaN(val) && mode === "add" ? val * (1 + tvaMultiplier) : NaN;
  const faraTva =
    !isNaN(val) && mode === "extract" ? val / (1 + tvaMultiplier) : NaN;
  const tvaAmount = !isNaN(val)
    ? mode === "add"
      ? val * tvaMultiplier
      : val - val / (1 + tvaMultiplier)
    : NaN;

  const fmt = (n: number) =>
    isNaN(n)
      ? "—"
      : n.toLocaleString("ro-RO", {
          minimumFractionDigits: 2,
          maximumFractionDigits: 2,
        });

  return (
    <div className="space-y-4">
      {/* Rate selector */}
      <div>
        <Label className="text-xs text-muted-foreground">Cotă TVA</Label>
        <div className="mt-1 flex flex-wrap items-center gap-2">
          {TVA_PRESETS.map((r) => (
            <Button
              key={r}
              type="button"
              variant={tvaRate === r && customRate === "" ? "default" : "outline"}
              size="sm"
              onClick={() => { setTvaRate(r); setCustomRate(""); }}
            >
              {r}%
            </Button>
          ))}
          <div className="flex items-center gap-1">
            <Input
              type="number"
              min={0}
              max={100}
              step={0.5}
              value={customRate}
              onChange={(e) => setCustomRate(e.target.value)}
              placeholder="Altă cotă"
              className="w-28 text-sm"
            />
            {customRate && (
              <span className="text-xs text-muted-foreground">%</span>
            )}
          </div>
        </div>
      </div>
      <div className="flex gap-2">
        <Button
          variant={mode === "add" ? "default" : "outline"}
          size="sm"
          onClick={() => setMode("add")}
        >
          Adaugă TVA
        </Button>
        <Button
          variant={mode === "extract" ? "default" : "outline"}
          size="sm"
          onClick={() => setMode("extract")}
        >
          Extrage TVA
        </Button>
      </div>
      <div>
        <Label>{mode === "add" ? "Sumă fără TVA" : "Sumă cu TVA"}</Label>
        <div className="mt-1 flex gap-2">
          <Input
            type="number"
            value={amount}
            onChange={(e) => setAmount(e.target.value)}
            placeholder={mode === "add" ? "Ex: 1000" : "Ex: 1190"}
            className="flex-1"
          />
          <span className="flex items-center text-sm text-muted-foreground">
            RON
          </span>
        </div>
      </div>
      {!isNaN(val) && val > 0 && (
        <div className="rounded-md border bg-muted/30 p-4 space-y-2 text-sm">
          {mode === "add" ? (
            <>
              <p>
                Sumă fără TVA: <strong>{fmt(val)} RON</strong>
              </p>
              <p>
                TVA ({effectiveRate}%): <strong>{fmt(tvaAmount)} RON</strong>
                <CopyButton text={fmt(tvaAmount)} />
              </p>
              <p className="text-base pt-1 border-t">
                Total cu TVA:{" "}
                <strong className="text-primary">{fmt(cuTva)} RON</strong>
                <CopyButton text={fmt(cuTva)} />
              </p>
            </>
          ) : (
            <>
              <p>
                Sumă cu TVA: <strong>{fmt(val)} RON</strong>
              </p>
              <p>
                TVA ({effectiveRate}%): <strong>{fmt(tvaAmount)} RON</strong>
                <CopyButton text={fmt(tvaAmount)} />
              </p>
              <p className="text-base pt-1 border-t">
                Sumă fără TVA:{" "}
                <strong className="text-primary">{fmt(faraTva)} RON</strong>
                <CopyButton text={fmt(faraTva)} />
              </p>
            </>
          )}
        </div>
      )}
    </div>
  );
}

function AreaConverter() {
  const units = [
    { key: "mp", label: "mp (m²)", factor: 1 },
    { key: "ari", label: "ari (100 m²)", factor: 100 },
    { key: "ha", label: "hectare (10.000 m²)", factor: 10000 },
    { key: "km2", label: "km²", factor: 1000000 },
    { key: "sqft", label: "sq ft", factor: 1 / 10.7639 },
  ] as const;

  const [values, setValues] = useState<Record<string, string>>({});
  const [activeField, setActiveField] = useState<string | null>(null);

  const handleChange = (key: string, raw: string) => {
    if (raw === "") {
      setValues({});
      return;
    }
    const v = parseFloat(raw);
    if (isNaN(v)) return;
    const unit = units.find((u) => u.key === key);
    if (!unit) return;
    const mp = v * unit.factor;
    const next: Record<string, string> = {};
    for (const u of units) {
      next[u.key] =
        u.key === key
          ? raw
          : (mp / u.factor).toPrecision(8).replace(/\.?0+$/, "");
    }
    setValues(next);
  };

  return (
    <div className="space-y-3">
      <p className="text-xs text-muted-foreground">
        Introdu o valoare în orice câmp — celelalte se calculează automat.
      </p>
      <div className="space-y-2">
        {units.map((u) => (
          <div key={u.key} className="flex items-center gap-2">
            <span className="w-36 text-xs text-muted-foreground">
              {u.label}
            </span>
            <Input
              type="number"
              value={values[u.key] ?? ""}
              onFocus={() => setActiveField(u.key)}
              onBlur={() => setActiveField(null)}
              onChange={(e) => handleChange(u.key, e.target.value)}
              className={`flex-1 ${activeField === u.key ? "ring-1 ring-primary" : ""}`}
              placeholder="0"
            />
            <CopyButton text={values[u.key] ?? ""} />
          </div>
        ))}
      </div>
    </div>
  );
}

// ─── U-value → R-value Converter ─────────────────────────────────────────────

function UValueConverter() {
  const [mode, setMode] = useState<"u-to-r" | "r-to-u">("u-to-r");
  const [uValue, setUValue] = useState("");
  const [rInput, setRInput] = useState("");
  const [thickness, setThickness] = useState("");

  const rsi = 0.13;
  const rse = 0.04;

  // U → R
  const u = parseFloat(uValue);
  const rFromU = !isNaN(u) && u > 0 ? (1 / u).toFixed(4) : null;
  const rTotalFromU =
    rFromU !== null ? (parseFloat(rFromU) + rsi + rse).toFixed(4) : null;

  // R → U
  const rIn = parseFloat(rInput);
  const uFromR = !isNaN(rIn) && rIn > 0 ? (1 / rIn).toFixed(4) : null;
  const rTotalFromR = uFromR !== null ? (rIn + rsi + rse).toFixed(4) : null;

  const activeR = mode === "u-to-r" ? rFromU : rInput || null;
  const activeU = mode === "u-to-r" ? uValue || null : uFromR;
  const activeRTotal = mode === "u-to-r" ? rTotalFromU : rTotalFromR;

  const t = parseFloat(thickness);
  const lambda =
    activeR !== null && !isNaN(t) && t > 0
      ? (t / 100 / parseFloat(activeR)).toFixed(4)
      : null;

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-2">
        <Button
          variant={mode === "u-to-r" ? "default" : "outline"}
          size="sm"
          onClick={() => {
            setMode("u-to-r");
            setRInput("");
          }}
        >
          U → R
        </Button>
        <Button
          variant={mode === "r-to-u" ? "default" : "outline"}
          size="sm"
          onClick={() => {
            setMode("r-to-u");
            setUValue("");
          }}
        >
          R → U
        </Button>
      </div>
      <div className="grid gap-3 sm:grid-cols-2">
        {mode === "u-to-r" ? (
          <div>
            <Label>Coeficient U (W/m²K)</Label>
            <Input
              type="number"
              step="0.01"
              min="0"
              value={uValue}
              onChange={(e) => setUValue(e.target.value)}
              className="mt-1"
              placeholder="ex: 0.35"
            />
          </div>
        ) : (
          <div>
            <Label>Rezistență termică R (m²K/W)</Label>
            <Input
              type="number"
              step="0.01"
              min="0"
              value={rInput}
              onChange={(e) => setRInput(e.target.value)}
              className="mt-1"
              placeholder="ex: 2.86"
            />
          </div>
        )}
        <div>
          <Label>Grosime material (cm) — opțional</Label>
          <Input
            type="number"
            step="0.1"
            min="0"
            value={thickness}
            onChange={(e) => setThickness(e.target.value)}
            className="mt-1"
            placeholder="ex: 20"
          />
        </div>
      </div>
      {(activeR !== null || activeU !== null) && (
        <div className="space-y-2 rounded-md border bg-muted/30 p-3 text-sm">
          {mode === "u-to-r" && rFromU !== null && (
            <div className="flex items-center justify-between">
              <span className="font-medium">R = 1/U</span>
              <div className="flex items-center gap-1">
                <code className="rounded border bg-muted px-2 py-0.5">
                  {rFromU} m²K/W
                </code>
                <CopyButton text={rFromU} />
              </div>
            </div>
          )}
          {mode === "r-to-u" && uFromR !== null && (
            <div className="flex items-center justify-between">
              <span className="font-medium">U = 1/R</span>
              <div className="flex items-center gap-1">
                <code className="rounded border bg-muted px-2 py-0.5">
                  {uFromR} W/m²K
                </code>
                <CopyButton text={uFromR} />
              </div>
            </div>
          )}
          <div className="flex items-center justify-between text-muted-foreground">
            <span>Rsi (suprafață interioară)</span>
            <code className="rounded border bg-muted px-2 py-0.5">
              {rsi} m²K/W
            </code>
          </div>
          <div className="flex items-center justify-between text-muted-foreground">
            <span>Rse (suprafață exterioară)</span>
            <code className="rounded border bg-muted px-2 py-0.5">
              {rse} m²K/W
            </code>
          </div>
          {activeRTotal !== null && (
            <div className="flex items-center justify-between font-medium border-t pt-2 mt-1">
              <span>R total (cu Rsi + Rse)</span>
              <div className="flex items-center gap-1">
                <code className="rounded border bg-muted px-2 py-0.5">
                  {activeRTotal} m²K/W
                </code>
                <CopyButton text={activeRTotal} />
              </div>
            </div>
          )}
          {lambda !== null && (
            <div className="flex items-center justify-between text-muted-foreground border-t pt-2 mt-1">
              <span>Conductivitate λ = d/R</span>
              <div className="flex items-center gap-1">
                <code className="rounded border bg-muted px-2 py-0.5">
                  {lambda} W/mK
                </code>
                <CopyButton text={lambda} />
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ─── Material Thermal Comparison ─────────────────────────────────────────────

interface ThermalMaterial {
  id: string;
  name: string;
  lambda: number; // W/mK — design value (λD) from Romanian technical sheets
  category: string;
  source: string; // brand / standard reference
}

// λD values from Romanian-market technical data sheets (fișe tehnice)
// Sources: Austrotherm, ISOVER, Knauf Insulation, Ytong/Xella, Porotherm/Wienerberger,
// Baumit, Caparol, Tondach, SR EN ISO 10456, C107
const THERMAL_MATERIALS: ThermalMaterial[] = [
  // Termoizolații
  {
    id: "eps-70",
    name: "Polistiren expandat EPS 70",
    lambda: 0.037,
    category: "Termoizolații",
    source: "Austrotherm EPS A70",
  },
  {
    id: "eps-80",
    name: "Polistiren expandat EPS 80",
    lambda: 0.035,
    category: "Termoizolații",
    source: "Austrotherm EPS A80",
  },
  {
    id: "eps-100",
    name: "Polistiren expandat EPS 100",
    lambda: 0.033,
    category: "Termoizolații",
    source: "Austrotherm EPS A100",
  },
  {
    id: "eps-graf",
    name: "Polistiren grafitat (EPS-G)",
    lambda: 0.031,
    category: "Termoizolații",
    source: "Austrotherm EPS A150 Grafit",
  },
  {
    id: "xps-30",
    name: "Polistiren extrudat XPS 30",
    lambda: 0.034,
    category: "Termoizolații",
    source: "Austrotherm XPS TOP 30",
  },
  {
    id: "xps-50",
    name: "Polistiren extrudat XPS 50",
    lambda: 0.036,
    category: "Termoizolații",
    source: "Austrotherm XPS TOP 50",
  },
  {
    id: "vata-min",
    name: "Vată minerală bazaltică",
    lambda: 0.036,
    category: "Termoizolații",
    source: "ISOVER PLE / Knauf TP 136",
  },
  {
    id: "vata-stc",
    name: "Vată minerală de sticlă",
    lambda: 0.035,
    category: "Termoizolații",
    source: "ISOVER Uniroll Plus",
  },
  {
    id: "pu-spray",
    name: "Spumă poliuretanică (PUR)",
    lambda: 0.024,
    category: "Termoizolații",
    source: "Basf Elastopor",
  },
  {
    id: "pir",
    name: "Plăci PIR (poliizocianurat)",
    lambda: 0.022,
    category: "Termoizolații",
    source: "Pir/Kingspan",
  },
  // Zidărie
  {
    id: "bca-35",
    name: "BCA densitate 350 kg/m³",
    lambda: 0.09,
    category: "Zidărie",
    source: "Ytong A+ PP2/0.35",
  },
  {
    id: "bca-40",
    name: "BCA densitate 400 kg/m³",
    lambda: 0.1,
    category: "Zidărie",
    source: "Ytong / Celco 400",
  },
  {
    id: "bca-50",
    name: "BCA densitate 500 kg/m³",
    lambda: 0.13,
    category: "Zidărie",
    source: "Celco A+ 500",
  },
  {
    id: "bca-60",
    name: "BCA densitate 600 kg/m³",
    lambda: 0.16,
    category: "Zidărie",
    source: "Ytong PP4/0.6",
  },
  {
    id: "poro-30",
    name: "Porotherm 30 N+F",
    lambda: 0.21,
    category: "Zidărie",
    source: "Wienerberger Porotherm 30",
  },
  {
    id: "poro-38",
    name: "Porotherm 38 Thermo",
    lambda: 0.16,
    category: "Zidărie",
    source: "Wienerberger Porotherm 38 Thermo",
  },
  {
    id: "poro-44",
    name: "Porotherm 44 Thermo",
    lambda: 0.13,
    category: "Zidărie",
    source: "Wienerberger Porotherm 44 Thermo",
  },
  {
    id: "car-plin",
    name: "Cărămidă plină presată",
    lambda: 0.74,
    category: "Zidărie",
    source: "C107 / SR EN ISO 10456",
  },
  {
    id: "car-gol",
    name: "Cărămidă cu goluri G25",
    lambda: 0.46,
    category: "Zidărie",
    source: "C107 / SR EN ISO 10456",
  },
  // Tencuieli / Finisaje
  {
    id: "tenc-term",
    name: "Tencuială termoizolantă",
    lambda: 0.08,
    category: "Tencuieli",
    source: "Baumit ThermoExtra",
  },
  {
    id: "tenc-var",
    name: "Tencuială var-ciment",
    lambda: 0.87,
    category: "Tencuieli",
    source: "C107 / SR EN ISO 10456",
  },
  {
    id: "tenc-cem",
    name: "Mortar de ciment",
    lambda: 1.0,
    category: "Tencuieli",
    source: "C107 / SR EN ISO 10456",
  },
  {
    id: "gips-cart",
    name: "Gips-carton",
    lambda: 0.25,
    category: "Tencuieli",
    source: "Knauf / Rigips",
  },
  {
    id: "tenc-dec",
    name: "Tencuială decorativă",
    lambda: 0.7,
    category: "Tencuieli",
    source: "Baumit / Caparol",
  },
  // Structură
  {
    id: "beton",
    name: "Beton armat",
    lambda: 1.74,
    category: "Structură",
    source: "C107 / SR EN ISO 10456",
  },
  {
    id: "lemn-mol",
    name: "Lemn molid/brad",
    lambda: 0.14,
    category: "Structură",
    source: "C107 / SR EN ISO 10456",
  },
  {
    id: "osb",
    name: "Plăci OSB",
    lambda: 0.13,
    category: "Structură",
    source: "Egger / Kronospan",
  },
  {
    id: "clt",
    name: "Lemn CLT (cross-laminated)",
    lambda: 0.12,
    category: "Structură",
    source: "Stora Enso / Binderholz",
  },
  // Hidroizolații / Bariere
  {
    id: "bpv",
    name: "Barieră de vapori (PE)",
    lambda: 0.4,
    category: "Bariere/Hidro",
    source: "Bramac / Dörken Delta",
  },
  {
    id: "hidro-bit",
    name: "Membrană bituminoasă",
    lambda: 0.23,
    category: "Bariere/Hidro",
    source: "IKO Armourbase / Siplast",
  },
  {
    id: "hidro-pvc",
    name: "Membrană PVC/TPO",
    lambda: 0.16,
    category: "Bariere/Hidro",
    source: "Sika Sarnafil / Renolit",
  },
  {
    id: "folie-difuz",
    name: "Folie difuzie (sub-acoperiș)",
    lambda: 0.4,
    category: "Bariere/Hidro",
    source: "Bramac Pro / Dörken",
  },
  // Pardoseli / Învelitori
  {
    id: "sapa-cem",
    name: "Șapă ciment",
    lambda: 1.4,
    category: "Pardoseli",
    source: "C107 / SR EN ISO 10456",
  },
  {
    id: "sapa-anh",
    name: "Șapă anhidrit",
    lambda: 1.2,
    category: "Pardoseli",
    source: "Knauf FE 80 Eco",
  },
  {
    id: "gresie",
    name: "Gresie/Faianță ceramică",
    lambda: 1.3,
    category: "Pardoseli",
    source: "C107 / SR EN ISO 10456",
  },
  {
    id: "parchet",
    name: "Parchet lemn stejar",
    lambda: 0.18,
    category: "Pardoseli",
    source: "C107 / SR EN ISO 10456",
  },
  {
    id: "tigla-cer",
    name: "Țiglă ceramică",
    lambda: 1.0,
    category: "Pardoseli",
    source: "Tondach / Bramac",
  },
  {
    id: "tigla-bet",
    name: "Țiglă beton",
    lambda: 1.5,
    category: "Pardoseli",
    source: "Bramac",
  },
  {
    id: "tabl-falt",
    name: "Tablă fălțuită (oțel)",
    lambda: 50.0,
    category: "Pardoseli",
    source: "Lindab / Bilka",
  },
  // Umpluturi
  {
    id: "pietris",
    name: "Pietriș/Balast compactat",
    lambda: 2.0,
    category: "Umpluturi",
    source: "C107 / SR EN ISO 10456",
  },
  {
    id: "nisip",
    name: "Nisip compactat",
    lambda: 2.0,
    category: "Umpluturi",
    source: "C107 / SR EN ISO 10456",
  },
  {
    id: "argila-exp",
    name: "Argilă expandată (Leca)",
    lambda: 0.1,
    category: "Umpluturi",
    source: "Leca / Weber Saint-Gobain",
  },
  {
    id: "aer-inch",
    name: "Strat de aer închis (ventilat)",
    lambda: 0.025,
    category: "Umpluturi",
    source: "C107 (Rconvențional)",
  },
];

interface LayerEntry {
  materialId: string;
  thickness: number; // cm
}

interface CompositionTemplate {
  name: string;
  description: string;
  category: string;
  layers: LayerEntry[];
}

const COMPOSITION_TEMPLATES: CompositionTemplate[] = [
  // Pereți exteriori
  {
    name: "Perete BCA 30 + EPS 10",
    description: "Sistem clasic ETICS cu BCA",
    category: "Pereți exteriori",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "bca-40", thickness: 30 },
      { materialId: "eps-80", thickness: 10 },
      { materialId: "tenc-dec", thickness: 0.5 },
    ],
  },
  {
    name: "Perete BCA 30 + vată 10",
    description: "ETICS cu vată minerală (A1 foc)",
    category: "Pereți exteriori",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "bca-40", thickness: 30 },
      { materialId: "vata-min", thickness: 10 },
      { materialId: "tenc-dec", thickness: 0.5 },
    ],
  },
  {
    name: "Perete Porotherm 30 + EPS 10",
    description: "Ceramică + polistiren",
    category: "Pereți exteriori",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "poro-30", thickness: 30 },
      { materialId: "eps-80", thickness: 10 },
      { materialId: "tenc-dec", thickness: 0.5 },
    ],
  },
  {
    name: "Perete Porotherm 38 Thermo neizolat",
    description: "Bloc ceramic termoizolant, fără ETICS",
    category: "Pereți exteriori",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "poro-38", thickness: 38 },
      { materialId: "tenc-dec", thickness: 0.5 },
    ],
  },
  {
    name: "Perete Porotherm 44 Thermo neizolat",
    description: "Bloc ceramic termoizolant gros",
    category: "Pereți exteriori",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "poro-44", thickness: 44 },
      { materialId: "tenc-dec", thickness: 0.5 },
    ],
  },
  {
    name: "Perete cărămidă + tencuială termoizolantă",
    description: "Renovare cu termoizolantă Baumit",
    category: "Pereți exteriori",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "car-gol", thickness: 25 },
      { materialId: "tenc-term", thickness: 8 },
      { materialId: "tenc-dec", thickness: 0.5 },
    ],
  },
  {
    name: "Perete lemn CLT + vată",
    description: "Structură CLT cu izolație exterioară",
    category: "Pereți exteriori",
    layers: [
      { materialId: "gips-cart", thickness: 1.25 },
      { materialId: "clt", thickness: 10 },
      { materialId: "vata-min", thickness: 15 },
      { materialId: "folie-difuz", thickness: 0.05 },
      { materialId: "tenc-dec", thickness: 0.5 },
    ],
  },
  // Pereți subsol
  {
    name: "Perete subsol beton + XPS",
    description: "Fundație beton cu izolație XPS în pământ",
    category: "Pereți subsol",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "beton", thickness: 25 },
      { materialId: "hidro-bit", thickness: 0.5 },
      { materialId: "xps-30", thickness: 10 },
    ],
  },
  {
    name: "Perete subsol beton + XPS 15",
    description: "Fundație cu izolație sporită",
    category: "Pereți subsol",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "beton", thickness: 30 },
      { materialId: "hidro-bit", thickness: 0.5 },
      { materialId: "xps-30", thickness: 15 },
    ],
  },
  // Terase / Acoperișuri plate
  {
    name: "Terasă necirculabilă — clasic",
    description: "Placa beton + termoizolație + hidroizolație",
    category: "Terase",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "beton", thickness: 15 },
      { materialId: "bpv", thickness: 0.05 },
      { materialId: "eps-100", thickness: 15 },
      { materialId: "sapa-cem", thickness: 4 },
      { materialId: "hidro-bit", thickness: 1 },
    ],
  },
  {
    name: "Terasă necirculabilă — PIR",
    description: "Cu PIR pentru grosime minimă",
    category: "Terase",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "beton", thickness: 15 },
      { materialId: "bpv", thickness: 0.05 },
      { materialId: "pir", thickness: 10 },
      { materialId: "sapa-cem", thickness: 4 },
      { materialId: "hidro-bit", thickness: 1 },
    ],
  },
  {
    name: "Terasă circulabilă — gresie",
    description: "Terasă cu finisaj gresie pe plot",
    category: "Terase",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "beton", thickness: 15 },
      { materialId: "bpv", thickness: 0.05 },
      { materialId: "eps-100", thickness: 15 },
      { materialId: "sapa-cem", thickness: 5 },
      { materialId: "hidro-bit", thickness: 1 },
      { materialId: "gresie", thickness: 2 },
    ],
  },
  {
    name: "Acoperiș verde extensiv",
    description: "Strat vegetal pe terasă",
    category: "Terase",
    layers: [
      { materialId: "tenc-var", thickness: 1.5 },
      { materialId: "beton", thickness: 15 },
      { materialId: "bpv", thickness: 0.05 },
      { materialId: "xps-30", thickness: 15 },
      { materialId: "sapa-cem", thickness: 4 },
      { materialId: "hidro-pvc", thickness: 0.2 },
      { materialId: "argila-exp", thickness: 8 },
    ],
  },
  // Șarpante
  {
    name: "Șarpantă lemn + vată între căpriori",
    description: "Izolație între și sub căpriori, clasic",
    category: "Șarpante",
    layers: [
      { materialId: "gips-cart", thickness: 1.25 },
      { materialId: "bpv", thickness: 0.05 },
      { materialId: "vata-min", thickness: 20 },
      { materialId: "osb", thickness: 1.2 },
      { materialId: "folie-difuz", thickness: 0.05 },
      { materialId: "aer-inch", thickness: 4 },
      { materialId: "tigla-cer", thickness: 2 },
    ],
  },
  {
    name: "Șarpantă lemn + vată 30cm",
    description: "Izolație sporită suprapusă",
    category: "Șarpante",
    layers: [
      { materialId: "gips-cart", thickness: 1.25 },
      { materialId: "bpv", thickness: 0.05 },
      { materialId: "vata-min", thickness: 30 },
      { materialId: "osb", thickness: 1.2 },
      { materialId: "folie-difuz", thickness: 0.05 },
      { materialId: "aer-inch", thickness: 4 },
      { materialId: "tigla-cer", thickness: 2 },
    ],
  },
  {
    name: "Șarpantă cu tablă fălțuită",
    description: "Acoperiș metalic cu izolație vată",
    category: "Șarpante",
    layers: [
      { materialId: "gips-cart", thickness: 1.25 },
      { materialId: "bpv", thickness: 0.05 },
      { materialId: "vata-min", thickness: 25 },
      { materialId: "osb", thickness: 1.2 },
      { materialId: "folie-difuz", thickness: 0.05 },
      { materialId: "aer-inch", thickness: 4 },
      { materialId: "tabl-falt", thickness: 0.06 },
    ],
  },
  // Plăci pe sol
  {
    name: "Placă pe sol — EPS sub placă",
    description: "Izolație sub radier, clasic",
    category: "Plăci pe sol",
    layers: [
      { materialId: "parchet", thickness: 1.5 },
      { materialId: "sapa-cem", thickness: 6 },
      { materialId: "bpv", thickness: 0.05 },
      { materialId: "eps-100", thickness: 10 },
      { materialId: "hidro-bit", thickness: 0.5 },
      { materialId: "beton", thickness: 15 },
      { materialId: "pietris", thickness: 15 },
    ],
  },
  {
    name: "Placă pe sol — XPS sub placă",
    description: "XPS rezistent la umiditate",
    category: "Plăci pe sol",
    layers: [
      { materialId: "gresie", thickness: 1 },
      { materialId: "sapa-cem", thickness: 6 },
      { materialId: "bpv", thickness: 0.05 },
      { materialId: "xps-30", thickness: 10 },
      { materialId: "hidro-bit", thickness: 0.5 },
      { materialId: "beton", thickness: 15 },
      { materialId: "pietris", thickness: 15 },
    ],
  },
  {
    name: "Placă pe sol — izolație sporită 15cm",
    description: "Pentru clădiri nZEB",
    category: "Plăci pe sol",
    layers: [
      { materialId: "parchet", thickness: 1.5 },
      { materialId: "sapa-cem", thickness: 6 },
      { materialId: "bpv", thickness: 0.05 },
      { materialId: "xps-30", thickness: 15 },
      { materialId: "hidro-bit", thickness: 0.5 },
      { materialId: "beton", thickness: 15 },
      { materialId: "pietris", thickness: 15 },
    ],
  },
];

function MaterialThermalComparison() {
  const [layersA, setLayersA] = useState<LayerEntry[]>([
    { materialId: "tenc-var", thickness: 1.5 },
    { materialId: "bca-40", thickness: 30 },
    { materialId: "vata-min", thickness: 10 },
    { materialId: "tenc-dec", thickness: 0.5 },
  ]);
  const [layersB, setLayersB] = useState<LayerEntry[]>([
    { materialId: "tenc-var", thickness: 1.5 },
    { materialId: "poro-38", thickness: 38 },
    { materialId: "tenc-dec", thickness: 0.5 },
  ]);

  // Drag-and-drop reorder state
  const dragIdxRef = useRef<number | null>(null);
  const [dragOverIdx, setDragOverIdx] = useState<number | null>(null);

  const rsi = 0.13;
  const rse = 0.04;

  const categories = Array.from(
    new Set(THERMAL_MATERIALS.map((m) => m.category)),
  );
  const templateCategories = Array.from(
    new Set(COMPOSITION_TEMPLATES.map((t) => t.category)),
  );

  const calcR = (layers: LayerEntry[]): number => {
    let r = 0;
    for (const layer of layers) {
      const mat = THERMAL_MATERIALS.find((m) => m.id === layer.materialId);
      if (mat && layer.thickness > 0) {
        r += layer.thickness / 100 / mat.lambda;
      }
    }
    return r;
  };

  const rA = calcR(layersA);
  const rB = calcR(layersB);
  const rTotalA = rA + rsi + rse;
  const rTotalB = rB + rsi + rse;
  const uA = rTotalA > 0 ? 1 / rTotalA : 0;
  const uB = rTotalB > 0 ? 1 / rTotalB : 0;

  const updateLayer = (
    setLayers: React.Dispatch<React.SetStateAction<LayerEntry[]>>,
    idx: number,
    field: "materialId" | "thickness",
    value: string,
  ) => {
    setLayers((prev) => {
      const next = [...prev];
      const entry = next[idx];
      if (!entry) return prev;
      if (field === "materialId") {
        next[idx] = { ...entry, materialId: value };
      } else {
        next[idx] = { ...entry, thickness: parseFloat(value) || 0 };
      }
      return next;
    });
  };

  const addLayer = (
    setLayers: React.Dispatch<React.SetStateAction<LayerEntry[]>>,
  ) => {
    setLayers((prev) => [...prev, { materialId: "eps-80", thickness: 10 }]);
  };

  const removeLayer = (
    setLayers: React.Dispatch<React.SetStateAction<LayerEntry[]>>,
    idx: number,
  ) => {
    setLayers((prev) => prev.filter((_, i) => i !== idx));
  };

  const moveLayer = (
    setLayers: React.Dispatch<React.SetStateAction<LayerEntry[]>>,
    idx: number,
    direction: "up" | "down",
  ) => {
    setLayers((prev) => {
      const next = [...prev];
      const targetIdx = direction === "up" ? idx - 1 : idx + 1;
      if (targetIdx < 0 || targetIdx >= next.length) return prev;
      const a = next[idx];
      const b = next[targetIdx];
      if (!a || !b) return prev;
      next[idx] = b;
      next[targetIdx] = a;
      return next;
    });
  };

  const applyTemplate = (
    setLayers: React.Dispatch<React.SetStateAction<LayerEntry[]>>,
    template: CompositionTemplate,
  ) => {
    setLayers(template.layers.map((l) => ({ ...l })));
  };

  const renderComposition = (
    label: string,
    layers: LayerEntry[],
    setLayers: React.Dispatch<React.SetStateAction<LayerEntry[]>>,
    r: number,
    rTotal: number,
    u: number,
  ) => (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <h4 className="text-sm font-semibold">{label}</h4>
        <select
          onChange={(e) => {
            const tpl = COMPOSITION_TEMPLATES.find(
              (t) => t.name === e.target.value,
            );
            if (tpl) applyTemplate(setLayers, tpl);
            e.target.value = "";
          }}
          value=""
          className="rounded-md border border-border bg-background px-2 py-1 text-xs max-w-[200px]"
        >
          <option value="" disabled>
            Șablon...
          </option>
          {templateCategories.map((cat) => (
            <optgroup key={cat} label={cat}>
              {COMPOSITION_TEMPLATES.filter((t) => t.category === cat).map(
                (t) => (
                  <option key={t.name} value={t.name}>
                    {t.name}
                  </option>
                ),
              )}
            </optgroup>
          ))}
        </select>
      </div>

      {/* Interior label */}
      <div className="flex items-center gap-2 text-[10px] uppercase tracking-widest text-blue-500/60 font-medium">
        <div className="h-px flex-1 bg-blue-500/20" />
        Interior
        <div className="h-px flex-1 bg-blue-500/20" />
      </div>

      {layers.map((layer, idx) => {
        const mat = THERMAL_MATERIALS.find((m) => m.id === layer.materialId);
        return (
          <div
            key={idx}
            draggable
            onDragStart={(e) => {
              dragIdxRef.current = idx;
              e.dataTransfer.effectAllowed = "move";
            }}
            onDragOver={(e) => {
              e.preventDefault();
              e.dataTransfer.dropEffect = "move";
              setDragOverIdx(idx);
            }}
            onDragLeave={() => setDragOverIdx(null)}
            onDrop={(e) => {
              e.preventDefault();
              const from = dragIdxRef.current;
              if (from !== null && from !== idx) {
                setLayers((prev) => {
                  const next = [...prev];
                  const item = next[from];
                  if (!item) return prev;
                  next.splice(from, 1);
                  next.splice(idx, 0, item);
                  return next;
                });
              }
              dragIdxRef.current = null;
              setDragOverIdx(null);
            }}
            onDragEnd={() => {
              dragIdxRef.current = null;
              setDragOverIdx(null);
            }}
            className={`flex gap-1.5 items-end cursor-grab active:cursor-grabbing transition-all ${
              dragOverIdx === idx
                ? "border-t-2 border-primary"
                : "border-t-2 border-transparent"
            }`}
          >
            {/* Move up/down */}
            <div className="flex flex-col gap-0.5 shrink-0">
              {idx === 0 && (
                <Label className="text-xs text-transparent">↕</Label>
              )}
              <div className="flex flex-col">
                <button
                  type="button"
                  onClick={() => moveLayer(setLayers, idx, "up")}
                  disabled={idx === 0}
                  className="h-4 w-5 flex items-center justify-center text-muted-foreground hover:text-foreground disabled:opacity-20 disabled:cursor-default"
                >
                  <ArrowUp className="h-3 w-3" />
                </button>
                <button
                  type="button"
                  onClick={() => moveLayer(setLayers, idx, "down")}
                  disabled={idx === layers.length - 1}
                  className="h-4 w-5 flex items-center justify-center text-muted-foreground hover:text-foreground disabled:opacity-20 disabled:cursor-default"
                >
                  <ArrowDown className="h-3 w-3" />
                </button>
              </div>
            </div>
            <div className="flex-1 min-w-0">
              {idx === 0 && (
                <Label className="text-xs text-muted-foreground">
                  Material
                </Label>
              )}
              <select
                value={layer.materialId}
                onChange={(e) =>
                  updateLayer(setLayers, idx, "materialId", e.target.value)
                }
                className="mt-0.5 w-full rounded-md border border-border bg-background px-2 py-1.5 text-sm"
              >
                {categories.map((cat) => (
                  <optgroup key={cat} label={cat}>
                    {THERMAL_MATERIALS.filter((m) => m.category === cat).map(
                      (m) => (
                        <option key={m.id} value={m.id}>
                          {m.name} (λ={m.lambda})
                        </option>
                      ),
                    )}
                  </optgroup>
                ))}
              </select>
            </div>
            <div className="w-16 shrink-0">
              {idx === 0 && (
                <Label className="text-xs text-muted-foreground">cm</Label>
              )}
              <Input
                type="number"
                min="0"
                step="0.5"
                value={layer.thickness || ""}
                onChange={(e) =>
                  updateLayer(setLayers, idx, "thickness", e.target.value)
                }
                className="mt-0.5"
              />
            </div>
            <div className="w-20 shrink-0 text-right">
              {idx === 0 && (
                <Label className="text-xs text-muted-foreground">R</Label>
              )}
              <div className="mt-0.5 rounded-md border bg-muted/30 px-1.5 py-1.5 text-xs text-right tabular-nums">
                {mat && layer.thickness > 0
                  ? (layer.thickness / 100 / mat.lambda).toFixed(3)
                  : "—"}
              </div>
            </div>
            {layers.length > 1 && (
              <Button
                variant="ghost"
                size="sm"
                className="h-8 w-8 p-0 text-muted-foreground hover:text-destructive shrink-0"
                onClick={() => removeLayer(setLayers, idx)}
              >
                ×
              </Button>
            )}
          </div>
        );
      })}

      {/* Exterior label */}
      <div className="flex items-center gap-2 text-[10px] uppercase tracking-widest text-orange-500/60 font-medium">
        <div className="h-px flex-1 bg-orange-500/20" />
        Exterior
        <div className="h-px flex-1 bg-orange-500/20" />
      </div>

      <Button variant="outline" size="sm" onClick={() => addLayer(setLayers)}>
        + Strat
      </Button>

      <div className="rounded-md border bg-muted/30 p-3 text-sm space-y-1.5">
        <div className="flex justify-between">
          <span className="text-muted-foreground">R straturi</span>
          <code className="rounded border bg-muted px-2 py-0.5 tabular-nums">
            {r.toFixed(3)} m²K/W
          </code>
        </div>
        <div className="flex justify-between">
          <span className="text-muted-foreground">
            + Rsi ({rsi}) + Rse ({rse})
          </span>
          <code className="rounded border bg-muted px-2 py-0.5 tabular-nums">
            {rTotal.toFixed(3)} m²K/W
          </code>
        </div>
        <div className="flex justify-between font-medium border-t pt-1.5">
          <span>U = 1/R total</span>
          <code className="rounded border bg-muted px-2 py-0.5 tabular-nums">
            {u.toFixed(3)} W/m²K
          </code>
        </div>
      </div>
    </div>
  );

  const diff = uA > 0 && uB > 0 ? ((uA - uB) / uA) * 100 : 0;
  const betterSide = uA < uB ? "A" : uA > uB ? "B" : null;

  return (
    <div className="space-y-4">
      <p className="text-sm text-muted-foreground">
        Compară două alcătuiri — prima de sus în jos (interior → exterior).
        Trage straturile cu mouse-ul pentru reordonare sau folosește săgețile
        ↑↓. Dropdown-ul „Șablon" încarcă sisteme prestabilite.
      </p>
      <div className="grid gap-6 lg:grid-cols-2">
        {renderComposition("Alcătuire A", layersA, setLayersA, rA, rTotalA, uA)}
        {renderComposition("Alcătuire B", layersB, setLayersB, rB, rTotalB, uB)}
      </div>
      {betterSide && (
        <div className="rounded-lg border-2 border-primary/30 bg-primary/5 p-4 text-sm">
          <span className="font-semibold">Verdict:</span> Alcătuirea{" "}
          {betterSide} izolează mai bine cu{" "}
          <span className="font-bold">{Math.abs(diff).toFixed(1)}%</span> (U
          {betterSide === "A" ? "A" : "B"} ={" "}
          {(betterSide === "A" ? uA : uB).toFixed(3)} vs U
          {betterSide === "A" ? "B" : "A"} ={" "}
          {(betterSide === "A" ? uB : uA).toFixed(3)} W/m²K).
          {(betterSide === "A" ? uA : uB) <= 0.28 && (
            <span className="block mt-1 text-green-600 dark:text-green-400">
              Îndeplinește cerința C107 pentru perete exterior (U ≤ 0.28 W/m²K).
            </span>
          )}
        </div>
      )}
    </div>
  );
}

// ─── AI Artifact Cleaner ──────────────────────────────────────────────────────

function AiArtifactCleaner() {
  const [input, setInput] = useState("");

  const clean = (text: string): string => {
    let r = text;
    // Strip markdown
    r = r.replace(/^#{1,6}\s+/gm, "");
    r = r.replace(/\*\*(.+?)\*\*/g, "$1");
    r = r.replace(/\*(.+?)\*/g, "$1");
    r = r.replace(/_{2}(.+?)_{2}/g, "$1");
    r = r.replace(/_(.+?)_/g, "$1");
    r = r.replace(/```[\s\S]*?```/g, "");
    r = r.replace(/`(.+?)`/g, "$1");
    r = r.replace(/^[*\-+]\s+/gm, "");
    r = r.replace(/^\d+\.\s+/gm, "");
    r = r.replace(/^[-_*]{3,}$/gm, "");
    r = r.replace(/\[(.+?)\]\(.*?\)/g, "$1");
    r = r.replace(/^>\s+/gm, "");
    // Fix encoding artifacts (UTF-8 mojibake)
    r = r.replace(/Ã¢/g, "â");
    r = r.replace(/Ã®/g, "î");
    r = r.replace(/Ã /g, "à");
    r = r.replace(/Å£/g, "ț");
    r = r.replace(/È™/g, "ș");
    r = r.replace(/È›/g, "ț");
    r = r.replace(/Èš/g, "Ț");
    r = r.replace(/\u015f/g, "ș");
    r = r.replace(/\u0163/g, "ț");
    // Remove zero-width and invisible chars
    r = r.replace(/[\u200b\u200c\u200d\ufeff]/g, "");
    // Remove emoji
    r = r.replace(/\p{Extended_Pictographic}/gu, "");
    r = r.replace(/[\u{1F1E0}-\u{1F1FF}]/gu, ""); // flag emoji
    r = r.replace(/[\u{FE00}-\u{FE0F}\u{20D0}-\u{20FF}]/gu, ""); // variation selectors
    // Normalize typography
    r = r.replace(/[""]/g, '"');
    r = r.replace(/['']/g, "'");
    r = r.replace(/[–—]/g, "-");
    r = r.replace(/…/g, "...");
    // Normalize spacing
    r = r.replace(/ {2,}/g, " ");
    r = r.replace(/\n{3,}/g, "\n\n");
    return r.trim();
  };

  const cleaned = input ? clean(input) : "";

  return (
    <div className="space-y-3">
      <div className="grid gap-3 sm:grid-cols-2">
        <div>
          <Label>Text original (output AI)</Label>
          <Textarea
            value={input}
            onChange={(e) => setInput(e.target.value)}
            className="mt-1 h-72 font-mono text-xs"
            placeholder="Lipește textul generat de AI..."
          />
        </div>
        <div>
          <div className="flex items-center justify-between">
            <Label>Text curățat</Label>
            {cleaned && <CopyButton text={cleaned} />}
          </div>
          <Textarea
            value={cleaned}
            readOnly
            className="mt-1 h-72 font-mono text-xs bg-muted/30"
          />
        </div>
      </div>
      <p className="text-xs text-muted-foreground">
        Operații: eliminare markdown (###, **, `, liste, citate), emoji,
        corectare encoding românesc (mojibake), curățare Unicode invizibil,
        normalizare ghilimele / cratime / spații multiple.
      </p>
    </div>
  );
}

// ─── MDLPA Date Locale ────────────────────────────────────────────────────────

function MdlpaValidator() {
  return (
    <div className="space-y-4">
      <p className="text-sm text-muted-foreground">
        Portalul MDLPA nu permite încadrarea în iframe (blochează via
        X-Frame-Options). Folosește linkurile de mai jos pentru a accesa direct
        portalul.
      </p>
      <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
        <a
          href="https://datelocale.mdlpa.ro"
          target="_blank"
          rel="noopener noreferrer"
          className="flex flex-col gap-1 rounded-lg border p-4 transition-colors hover:bg-muted/50"
        >
          <span className="font-medium text-primary">Portalul principal ↗</span>
          <span className="text-xs text-muted-foreground">
            datelocale.mdlpa.ro — date locale construcții
          </span>
        </a>
        <a
          href="https://datelocale.mdlpa.ro/ro/about/tutorials"
          target="_blank"
          rel="noopener noreferrer"
          className="flex flex-col gap-1 rounded-lg border p-4 transition-colors hover:bg-muted/50"
        >
          <span className="font-medium text-primary">Tutoriale video ↗</span>
          <span className="text-xs text-muted-foreground">
            Ghiduri de utilizare pas cu pas
          </span>
        </a>
        <a
          href="https://datelocale.mdlpa.ro/ro/about/info/reguli"
          target="_blank"
          rel="noopener noreferrer"
          className="flex flex-col gap-1 rounded-lg border p-4 transition-colors hover:bg-muted/50"
        >
          <span className="font-medium text-primary">Reguli de calcul ↗</span>
          <span className="text-xs text-muted-foreground">
            Metodologie și formule de calcul
          </span>
        </a>
      </div>
    </div>
  );
}

// ─── PDF Reducer (Stirling PDF) ───────────────────────────────────────────────

function formatBytes(bytes: number) {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
}

function PdfReducer() {
  const [file, setFile] = useState<File | null>(null);
  const [mode, setMode] = useState<"extreme" | "max" | "balanced">("extreme");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [result, setResult] = useState<{
    originalSize: number;
    compressedSize: number;
  } | null>(null);
  const [dragging, setDragging] = useState(false);
  const fileRef = useRef<HTMLInputElement>(null);

  const setFileFromInput = (f: File | null) => {
    setFile(f);
    setError("");
    setResult(null);
  };

  const handleCompress = async () => {
    if (!file) return;
    setLoading(true);
    setError("");
    setResult(null);
    try {
      const formData = new FormData();
      formData.append("fileInput", file);
      // All modes use the GS endpoint with a level parameter
      formData.append("level", mode === "extreme" ? "extreme" : mode === "max" ? "high" : "balanced");

      const res = await fetch("/api/compress-pdf/extreme", {
        method: "POST",
        body: formData,
      });
      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        throw new Error(data.error ?? `Eroare server: ${res.status}`);
      }
      const blob = await res.blob();

      const origHeader = res.headers.get("X-Original-Size");
      const compHeader = res.headers.get("X-Compressed-Size");
      setResult({
        originalSize: origHeader ? Number(origHeader) : file.size,
        compressedSize: compHeader ? Number(compHeader) : blob.size,
      });

      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = file.name.replace(/\.pdf$/i, "-comprimat.pdf");
      a.click();
      URL.revokeObjectURL(url);
    } catch (err) {
      setError(
        err instanceof Error
          ? err.message
          : "Nu s-a putut contacta Stirling PDF.",
      );
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="space-y-4">
      <div className="space-y-1.5">
        <Label>Fișier PDF</Label>
        <input
          ref={fileRef}
          type="file"
          accept=".pdf"
          className="hidden"
          onChange={(e) => setFileFromInput(e.target.files?.[0] ?? null)}
        />
        <div
          tabIndex={0}
          className={`flex min-h-[80px] cursor-pointer flex-col items-center justify-center gap-1 rounded-md border-2 border-dashed p-4 text-sm transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring ${
            dragging
              ? "border-primary bg-primary/5"
              : "border-border text-muted-foreground hover:border-primary/50"
          }`}
          onClick={() => fileRef.current?.click()}
          onDragOver={(e) => {
            e.preventDefault();
            setDragging(true);
          }}
          onDragLeave={() => setDragging(false)}
          onDrop={(e) => {
            e.preventDefault();
            setDragging(false);
            const f = e.dataTransfer.files[0];
            if (f?.type === "application/pdf") setFileFromInput(f);
          }}
          onPaste={(e) => {
            const f = e.clipboardData.files[0];
            if (f?.type === "application/pdf") setFileFromInput(f);
          }}
        >
          {file ? (
            <span className="font-medium text-foreground">
              {file.name}{" "}
              <span className="text-muted-foreground">
                ({formatBytes(file.size)})
              </span>
            </span>
          ) : (
            <>
              <Upload className="h-5 w-5" />
              <span>Trage un PDF aici sau apasă pentru a selecta</span>
            </>
          )}
        </div>
      </div>

      <div className="space-y-1.5">
        <Label>Nivel compresie</Label>
        <select
          value={mode}
          onChange={(e) =>
            setMode(e.target.value as "extreme" | "max" | "balanced")
          }
          className="mt-1 w-full rounded-md border bg-background px-3 py-2 text-sm"
        >
          <option value="extreme">
            Extremă — imagini 100 DPI, calitate scăzută
          </option>
          <option value="max">Puternică — imagini 150 DPI, calitate medie (recomandat)</option>
          <option value="balanced">Echilibrată — imagini 200 DPI, calitate bună</option>
        </select>
        <p className="text-xs text-muted-foreground">
          {mode === "extreme"
            ? "Reduce maxim dimensiunea. Imaginile pot pierde detalii fine."
            : mode === "max"
              ? "Balanță bună între dimensiune și calitate. Recomandat pentru majoritatea fișierelor."
              : "Pierdere minimă de calitate. Ideal pentru documente cu grafice detaliate."}
        </p>
      </div>

      <Button onClick={handleCompress} disabled={!file || loading}>
        {loading ? "Se comprimă..." : "Comprimă PDF"}
      </Button>

      {result && (
        <div className="rounded-lg border bg-muted/30 p-3">
          <p className="text-sm font-medium">
            {formatBytes(result.originalSize)} →{" "}
            {formatBytes(result.compressedSize)}
            <span className="ml-2 font-bold text-green-600 dark:text-green-400">
              −
              {(
                ((result.originalSize - result.compressedSize) /
                  result.originalSize) *
                100
              ).toFixed(0)}
              % mai mic
            </span>
          </p>
        </div>
      )}

      {error && <p className="text-sm text-destructive">{error}</p>}
    </div>
  );
}

// ─── PDF Unlock (Stirling PDF) ────────────────────────────────────────────────

function PdfUnlock() {
  const [file, setFile] = useState<File | null>(null);
  const [password, setPassword] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [dragging, setDragging] = useState(false);
  const fileRef = useRef<HTMLInputElement>(null);

  const setFileFromInput = (f: File | null) => {
    setFile(f);
    setError("");
  };

  const handleUnlock = async () => {
    if (!file) return;
    setLoading(true);
    setError("");
    try {
      const formData = new FormData();
      formData.append("fileInput", file);
      formData.append("password", password);
      const res = await fetch("/api/compress-pdf/unlock", {
        method: "POST",
        body: formData,
      });
      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        throw new Error(data.error ?? `Eroare server: ${res.status}`);
      }
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = file.name.replace(/\.pdf$/i, "-deblocat.pdf");
      a.click();
      URL.revokeObjectURL(url);
    } catch (err) {
      setError(
        err instanceof Error ? err.message : "Nu s-a putut debloca PDF-ul.",
      );
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="space-y-4">
      <div className="space-y-1.5">
        <Label>Fișier PDF protejat</Label>
        <input
          ref={fileRef}
          type="file"
          accept=".pdf"
          className="hidden"
          onChange={(e) => setFileFromInput(e.target.files?.[0] ?? null)}
        />
        <div
          tabIndex={0}
          className={`flex min-h-[80px] cursor-pointer flex-col items-center justify-center gap-1 rounded-md border-2 border-dashed p-4 text-sm transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring ${
            dragging
              ? "border-primary bg-primary/5"
              : "border-border text-muted-foreground hover:border-primary/50"
          }`}
          onClick={() => fileRef.current?.click()}
          onDragOver={(e) => {
            e.preventDefault();
            setDragging(true);
          }}
          onDragLeave={() => setDragging(false)}
          onDrop={(e) => {
            e.preventDefault();
            setDragging(false);
            const f = e.dataTransfer.files[0];
            if (f?.type === "application/pdf") setFileFromInput(f);
          }}
          onPaste={(e) => {
            const f = e.clipboardData.files[0];
            if (f?.type === "application/pdf") setFileFromInput(f);
          }}
        >
          {file ? (
            <span className="font-medium text-foreground">{file.name}</span>
          ) : (
            <>
              <Upload className="h-5 w-5" />
              <span>Trage un PDF aici sau apasă pentru a selecta</span>
            </>
          )}
        </div>
      </div>

      <div className="space-y-1.5">
        <Label>Parolă (dacă e criptat cu parolă)</Label>
        <Input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="Lasă gol dacă nu are parolă"
          className="mt-1"
        />
      </div>

      <Button onClick={handleUnlock} disabled={!file || loading}>
        {loading ? "Se deblochează..." : "Deblochează PDF"}
      </Button>

      {error && <p className="text-sm text-destructive">{error}</p>}
    </div>
  );
}

// ─── DWG → DXF Converter ─────────────────────────────────────────────────────

function DwgToDxf() {
  const [file, setFile] = useState<File | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [dragging, setDragging] = useState(false);
  const fileRef = useRef<HTMLInputElement>(null);

  const setFileFromInput = (f: File | null) => {
    setFile(f);
    setError("");
  };

  const handleConvert = async () => {
    if (!file) return;
    setLoading(true);
    setError("");
    try {
      const formData = new FormData();
      formData.append("fileInput", file);
      const res = await fetch("/api/dwg-convert", {
        method: "POST",
        body: formData,
      });
      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        throw new Error(data.error ?? `Eroare server: ${res.status}`);
      }
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = file.name.replace(/\.dwg$/i, ".dxf");
      a.click();
      URL.revokeObjectURL(url);
    } catch (err) {
      setError(
        err instanceof Error ? err.message : "Nu s-a putut converti fișierul.",
      );
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="space-y-4">
      <div className="space-y-1.5">
        <Label>Fișier DWG</Label>
        <input
          ref={fileRef}
          type="file"
          accept=".dwg"
          className="hidden"
          onChange={(e) => setFileFromInput(e.target.files?.[0] ?? null)}
        />
        <div
          tabIndex={0}
          className={`flex min-h-[80px] cursor-pointer flex-col items-center justify-center gap-1 rounded-md border-2 border-dashed p-4 text-sm transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring ${
            dragging
              ? "border-primary bg-primary/5"
              : "border-border text-muted-foreground hover:border-primary/50"
          }`}
          onClick={() => fileRef.current?.click()}
          onDragOver={(e) => {
            e.preventDefault();
            setDragging(true);
          }}
          onDragLeave={() => setDragging(false)}
          onDrop={(e) => {
            e.preventDefault();
            setDragging(false);
            const f = e.dataTransfer.files[0];
            if (f?.name.toLowerCase().endsWith(".dwg")) setFileFromInput(f);
          }}
          onPaste={(e) => {
            const f = e.clipboardData.files[0];
            if (f?.name.toLowerCase().endsWith(".dwg")) setFileFromInput(f);
          }}
        >
          {file ? (
            <span className="font-medium text-foreground">{file.name}</span>
          ) : (
            <>
              <Upload className="h-5 w-5" />
              <span>Trage un fișier .dwg aici sau apasă pentru a selecta</span>
            </>
          )}
        </div>
      </div>

      <p className="text-xs text-muted-foreground">
        Convertește AutoCAD DWG în format DXF deschis. Suportă versiuni până la
        DWG 2018. Conversie server-side via libredwg.
      </p>

      <Button onClick={handleConvert} disabled={!file || loading}>
        {loading ? "Se convertește..." : "Convertește în DXF"}
      </Button>

      {error && <p className="text-sm text-destructive">{error}</p>}
    </div>
  );
}

// ─── Quick OCR ────────────────────────────────────────────────────────────────

function QuickOcr() {
  const [imageSrc, setImageSrc] = useState<string | null>(null);
  const [text, setText] = useState("");
  const [progress, setProgress] = useState(0);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [lang, setLang] = useState("ron+eng");
  const fileRef = useRef<HTMLInputElement>(null);

  const runOcr = async (src: string) => {
    if (loading) return;
    setLoading(true);
    setError("");
    setText("");
    setProgress(0);
    try {
      const { createWorker } = await import("tesseract.js");
      const worker = await createWorker(lang.split("+"), 1, {
        logger: (m: { status: string; progress: number }) => {
          if (m.status === "recognizing text")
            setProgress(Math.round(m.progress * 100));
        },
      });
      const { data } = await worker.recognize(src);
      setText(data.text.trim());
      await worker.terminate();
    } catch (e) {
      setError(e instanceof Error ? e.message : "Eroare OCR necunoscută");
    } finally {
      setLoading(false);
    }
  };

  const handleFile = (file: File) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const src = e.target?.result as string;
      setImageSrc(src);
      runOcr(src);
    };
    reader.readAsDataURL(file);
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    const file = Array.from(e.dataTransfer.files).find((f) =>
      f.type.startsWith("image/"),
    );
    if (file) handleFile(file);
  };

  const handlePaste = (e: React.ClipboardEvent) => {
    const item = Array.from(e.clipboardData.items).find((i) =>
      i.type.startsWith("image/"),
    );
    const file = item?.getAsFile();
    if (file) handleFile(file);
  };

  return (
    <div className="space-y-3" onPaste={handlePaste}>
      <div className="flex flex-wrap items-center gap-3">
        <select
          value={lang}
          onChange={(e) => setLang(e.target.value)}
          className="rounded-md border bg-background px-3 py-1.5 text-sm"
        >
          <option value="ron+eng">Română + Engleză</option>
          <option value="ron">Română</option>
          <option value="eng">Engleză</option>
        </select>
        <span className="text-xs text-muted-foreground">
          sau Ctrl+V pentru a lipi imaginea
        </span>
      </div>

      <div
        className="flex min-h-[120px] cursor-pointer items-center justify-center rounded-md border-2 border-dashed p-4 text-sm text-muted-foreground transition-colors hover:border-primary/50"
        onClick={() => fileRef.current?.click()}
        onDrop={handleDrop}
        onDragOver={(e) => e.preventDefault()}
      >
        {imageSrc ? (
          // eslint-disable-next-line @next/next/no-img-element
          <img
            src={imageSrc}
            alt="preview"
            className="max-h-48 max-w-full rounded object-contain"
          />
        ) : (
          <span>Trage o imagine aici, apasă pentru a selecta, sau Ctrl+V</span>
        )}
      </div>
      <input
        ref={fileRef}
        type="file"
        accept="image/*"
        className="hidden"
        onChange={(e) => {
          const f = e.target.files?.[0];
          if (f) handleFile(f);
        }}
      />

      {loading && (
        <div className="space-y-1">
          <div className="flex justify-between text-xs text-muted-foreground">
            <span>Se procesează... (primul rulaj descarcă modelul ~10 MB)</span>
            <span>{progress}%</span>
          </div>
          <div className="h-1.5 w-full overflow-hidden rounded-full bg-muted">
            <div
              className="h-full bg-primary transition-all"
              style={{ width: `${progress}%` }}
            />
          </div>
        </div>
      )}

      {error && <p className="text-sm text-destructive">{error}</p>}

      {text && (
        <div>
          <div className="flex items-center justify-between">
            <Label>Text extras</Label>
            <CopyButton text={text} />
          </div>
          <Textarea
            value={text}
            readOnly
            className="mt-1 h-56 font-mono text-xs bg-muted/30"
          />
        </div>
      )}
    </div>
  );
}

// ─── Number to Text (Romanian) ────────────────────────────────────────────────

const ONES = [
  "",
  "unu",
  "doi",
  "trei",
  "patru",
  "cinci",
  "șase",
  "șapte",
  "opt",
  "nouă",
  "zece",
  "unsprezece",
  "doisprezece",
  "treisprezece",
  "paisprezece",
  "cincisprezece",
  "șaisprezece",
  "șaptesprezece",
  "optsprezece",
  "nouăsprezece",
];
const TENS = [
  "",
  "zece",
  "douăzeci",
  "treizeci",
  "patruzeci",
  "cincizeci",
  "șaizeci",
  "șaptezeci",
  "optzeci",
  "nouăzeci",
];

function numberToRoText(n: number): string {
  if (n === 0) return "zero";
  if (n < 0) return "minus " + numberToRoText(-n);

  const parts: string[] = [];

  // Billions
  const mld = Math.floor(n / 1_000_000_000);
  if (mld > 0) {
    if (mld === 1) parts.push("un miliard");
    else if (mld < 20) parts.push(ONES[mld]! + " miliarde");
    else parts.push(twoDigitRo(mld) + " de miliarde");
    n %= 1_000_000_000;
  }

  // Millions
  const mil = Math.floor(n / 1_000_000);
  if (mil > 0) {
    if (mil === 1) parts.push("un milion");
    else if (mil < 20) parts.push(ONES[mil]! + " milioane");
    else parts.push(twoDigitRo(mil) + " de milioane");
    n %= 1_000_000;
  }

  // Thousands
  const th = Math.floor(n / 1000);
  if (th > 0) {
    if (th === 1) parts.push("o mie");
    else if (th === 2) parts.push("două mii");
    else if (th < 20) parts.push(ONES[th]! + " mii");
    else if (th < 100) parts.push(twoDigitRo(th) + " de mii");
    else parts.push(threeDigitRo(th) + " de mii");
    n %= 1000;
  }

  // Hundreds
  const h = Math.floor(n / 100);
  if (h > 0) {
    if (h === 1) parts.push("o sută");
    else if (h === 2) parts.push("două sute");
    else parts.push(ONES[h]! + " sute");
    n %= 100;
  }

  // Remainder < 100
  if (n > 0) {
    if (parts.length > 0) parts.push("și");
    if (n < 20) {
      parts.push(ONES[n]!);
    } else {
      parts.push(twoDigitRo(n));
    }
  }

  return parts.join(" ");
}

function twoDigitRo(n: number): string {
  if (n < 20) return ONES[n]!;
  const t = Math.floor(n / 10);
  const o = n % 10;
  if (o === 0) return TENS[t]!;
  return TENS[t]! + " și " + ONES[o]!;
}

function threeDigitRo(n: number): string {
  const h = Math.floor(n / 100);
  const rest = n % 100;
  let s = "";
  if (h === 1) s = "o sută";
  else if (h === 2) s = "două sute";
  else s = ONES[h]! + " sute";
  if (rest > 0) s += " " + twoDigitRo(rest);
  return s;
}

function NumberToText() {
  const [input, setInput] = useState("");

  const v = parseFloat(input);
  const isValid = !isNaN(v) && isFinite(v) && v >= 0 && v < 1e12;

  const intPart = isValid ? Math.floor(v) : 0;
  const decStr = input.includes(".") ? (input.split(".")[1] ?? "") : "";
  const decPart = decStr ? parseInt(decStr.slice(0, 2).padEnd(2, "0"), 10) : 0;

  const intText = isValid ? numberToRoText(intPart) : "";
  const decText = decPart > 0 ? numberToRoText(decPart) : "";

  // lei + bani version
  const leiBani = isValid
    ? intText + " lei" + (decPart > 0 ? " și " + decText + " de bani" : "")
    : "";

  // Compact (no spaces between groups)
  const compact = isValid
    ? intText.replace(/ și /g, "șI").replace(/ /g, "").replace(/șI/g, "și") +
      (decPart > 0
        ? " virgulă " +
          decText.replace(/ și /g, "șI").replace(/ /g, "").replace(/șI/g, "și")
        : "")
    : "";

  // Normal
  const normal = isValid
    ? intText + (decPart > 0 ? " virgulă " + decText : "")
    : "";

  return (
    <div className="space-y-3">
      <div>
        <Label>Sumă (număr)</Label>
        <Input
          type="number"
          step="0.01"
          min="0"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          className="mt-1"
          placeholder="ex: 432.20"
        />
      </div>
      {isValid && intText && (
        <div className="space-y-2">
          <div className="flex items-start gap-2 rounded-md border bg-muted/30 p-3">
            <div className="flex-1 text-sm">
              <p className="text-xs font-medium text-muted-foreground mb-1">
                Lei și bani
              </p>
              <p>{leiBani}</p>
            </div>
            <CopyButton text={leiBani} />
          </div>
          <div className="flex items-start gap-2 rounded-md border bg-muted/30 p-3">
            <div className="flex-1 text-sm">
              <p className="text-xs font-medium text-muted-foreground mb-1">
                Cu spații
              </p>
              <p>{normal}</p>
            </div>
            <CopyButton text={normal} />
          </div>
          <div className="flex items-start gap-2 rounded-md border bg-muted/30 p-3">
            <div className="flex-1 text-sm">
              <p className="text-xs font-medium text-muted-foreground mb-1">
                Compact (fără spații)
              </p>
              <p>{compact}</p>
            </div>
            <CopyButton text={compact} />
          </div>
        </div>
      )}
    </div>
  );
}

// ─── Color Palette Extractor ──────────────────────────────────────────────────

function ColorPaletteExtractor() {
  const [imageSrc, setImageSrc] = useState<string | null>(null);
  const [colors, setColors] = useState<string[]>([]);
  const [copiedIdx, setCopiedIdx] = useState<number | null>(null);
  const fileRef = useRef<HTMLInputElement>(null);

  const extractColors = useCallback((src: string) => {
    const img = new Image();
    img.crossOrigin = "anonymous";
    img.onload = () => {
      const canvas = document.createElement("canvas");
      const size = 100;
      canvas.width = size;
      canvas.height = size;
      const ctx = canvas.getContext("2d")!;
      ctx.drawImage(img, 0, 0, size, size);
      const data = ctx.getImageData(0, 0, size, size).data;

      // Simple K-means-ish clustering: bucket colors
      const buckets = new Map<
        string,
        { r: number; g: number; b: number; count: number }
      >();
      for (let i = 0; i < data.length; i += 4) {
        const r = Math.round(data[i]! / 32) * 32;
        const g = Math.round(data[i + 1]! / 32) * 32;
        const b = Math.round(data[i + 2]! / 32) * 32;
        const key = `${r},${g},${b}`;
        const existing = buckets.get(key);
        if (existing) {
          existing.r += data[i]!;
          existing.g += data[i + 1]!;
          existing.b += data[i + 2]!;
          existing.count++;
        } else {
          buckets.set(key, {
            r: data[i]!,
            g: data[i + 1]!,
            b: data[i + 2]!,
            count: 1,
          });
        }
      }

      const sorted = Array.from(buckets.values())
        .sort((a, b) => b.count - a.count)
        .slice(0, 8);

      const palette = sorted.map((b) => {
        const r = Math.round(b.r / b.count);
        const g = Math.round(b.g / b.count);
        const bl = Math.round(b.b / b.count);
        return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${bl.toString(16).padStart(2, "0")}`;
      });

      setColors(palette);
    };
    img.src = src;
  }, []);

  const handleFile = (file: File) => {
    if (!file.type.startsWith("image/")) return;
    const reader = new FileReader();
    reader.onload = (e) => {
      const src = e.target?.result as string;
      setImageSrc(src);
      extractColors(src);
    };
    reader.readAsDataURL(file);
  };

  const copyColor = async (hex: string, idx: number) => {
    try {
      await navigator.clipboard.writeText(hex.toUpperCase());
      setCopiedIdx(idx);
      setTimeout(() => setCopiedIdx(null), 1500);
    } catch {
      /* silent */
    }
  };

  return (
    <div className="space-y-4">
      <div
        tabIndex={0}
        className="flex min-h-[120px] cursor-pointer flex-col items-center justify-center gap-2 rounded-md border-2 border-dashed p-4 text-sm text-muted-foreground transition-colors outline-none hover:border-primary/50 focus-visible:ring-2 focus-visible:ring-ring"
        onClick={() => fileRef.current?.click()}
        onDragOver={(e) => e.preventDefault()}
        onDrop={(e) => {
          e.preventDefault();
          const f = e.dataTransfer.files[0];
          if (f) handleFile(f);
        }}
        onPaste={(e) => {
          const f = e.clipboardData.files[0];
          if (f) handleFile(f);
          // Also support pasting image data from clipboard
          const items = e.clipboardData.items;
          for (let i = 0; i < items.length; i++) {
            const item = items[i];
            if (item?.type.startsWith("image/")) {
              const blob = item.getAsFile();
              if (blob) handleFile(blob);
              break;
            }
          }
        }}
      >
        {imageSrc ? (
          // eslint-disable-next-line @next/next/no-img-element
          <img
            src={imageSrc}
            alt="preview"
            className="max-h-40 max-w-full rounded object-contain"
          />
        ) : (
          <>
            <Upload className="h-6 w-6" />
            <span>Trage o imagine, apasă, sau lipește (Ctrl+V)</span>
          </>
        )}
      </div>
      <input
        ref={fileRef}
        type="file"
        accept="image/*"
        className="hidden"
        onChange={(e) => {
          const f = e.target.files?.[0];
          if (f) handleFile(f);
        }}
      />
      {colors.length > 0 && (
        <div className="space-y-2">
          <Label>Paletă extrasă ({colors.length} culori)</Label>
          <div className="flex flex-wrap gap-2">
            {colors.map((hex, i) => (
              <button
                key={i}
                className="group relative flex flex-col items-center gap-1 rounded-lg border p-2 transition-colors hover:bg-muted/50"
                onClick={() => void copyColor(hex, i)}
                title={`Click pentru a copia ${hex.toUpperCase()}`}
              >
                <div
                  className="h-12 w-12 rounded-md border shadow-sm"
                  style={{ backgroundColor: hex }}
                />
                <code className="text-[10px] text-muted-foreground">
                  {copiedIdx === i ? "Copiat!" : hex.toUpperCase()}
                </code>
              </button>
            ))}
          </div>
          <div className="flex items-center gap-2 pt-1">
            <CopyButton text={colors.map((c) => c.toUpperCase()).join(", ")} />
            <span className="text-xs text-muted-foreground">
              Copiază toate culorile
            </span>
          </div>
        </div>
      )}
    </div>
  );
}

// ─── Calculator Scară ─────────────────────────────────────────────────────────

const SCALE_PRESETS = [
  { label: "1:20", value: 20 },
  { label: "1:50", value: 50 },
  { label: "1:100", value: 100 },
  { label: "1:200", value: 200 },
  { label: "1:500", value: 500 },
  { label: "1:1000", value: 1000 },
  { label: "1:5000", value: 5000 },
];

// Real unit → multiplier to convert to mm
const REAL_UNITS = [
  { id: "mm", label: "mm", toMm: 1 },
  { id: "cm", label: "cm", toMm: 10 },
  { id: "m",  label: "m",  toMm: 1_000 },
  { id: "km", label: "km", toMm: 1_000_000 },
] as const;
type RealUnit = (typeof REAL_UNITS)[number]["id"];

/**
 * Scale calculator.
 *
 * Core identity (all in mm):
 *   drawing_mm = real_mm / scale
 *   real_mm    = drawing_mm × scale
 *
 * Real input in any unit → convert to mm → apply scale → drawing in mm.
 * Drawing input in mm → apply scale → real mm → convert to chosen unit.
 */
function ScaleCalculator() {
  const [scale, setScale] = useState(100);
  const [customScale, setCustomScale] = useState("");
  const [mode, setMode] = useState<"real-to-drawing" | "drawing-to-real">("real-to-drawing");
  const [realUnit, setRealUnit] = useState<RealUnit>("cm");
  const [inputVal, setInputVal] = useState("");

  const effectiveScale = customScale !== "" ? parseFloat(customScale) || scale : scale;
  const val = parseFloat(inputVal);

  const unitDef = REAL_UNITS.find((u) => u.id === realUnit)!;

  // drawing_mm = real_in_unit × unitDef.toMm / scale
  // real_in_unit = drawing_mm × scale / unitDef.toMm
  const drawing_mm = !isNaN(val) && mode === "real-to-drawing"
    ? (val * unitDef.toMm) / effectiveScale
    : NaN;
  const real_in_unit = !isNaN(val) && mode === "drawing-to-real"
    ? (val * effectiveScale) / unitDef.toMm
    : NaN;

  // For secondary display: real_mm (whichever mode)
  const real_mm = mode === "real-to-drawing"
    ? val * unitDef.toMm
    : val * effectiveScale;

  const fmt = (n: number, decimals = 2) =>
    isNaN(n) || !isFinite(n)
      ? "—"
      : n.toLocaleString("ro-RO", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });

  // Build secondary real conversions (exclude current unit)
  const secondaryReal = (mm: number) =>
    REAL_UNITS.filter((u) => u.id !== realUnit)
      .map((u) => `${fmt(mm / u.toMm)} ${u.id}`)
      .join(" · ");

  return (
    <div className="space-y-4">
      {/* Scale picker */}
      <div>
        <Label className="text-xs text-muted-foreground">Scară</Label>
        <div className="mt-1 flex flex-wrap items-center gap-2">
          {SCALE_PRESETS.map((p) => (
            <Button
              key={p.value}
              type="button"
              variant={scale === p.value && customScale === "" ? "default" : "outline"}
              size="sm"
              onClick={() => { setScale(p.value); setCustomScale(""); }}
            >
              {p.label}
            </Button>
          ))}
          <div className="flex items-center gap-1">
            <span className="text-xs text-muted-foreground">1:</span>
            <Input
              type="number"
              min={1}
              value={customScale}
              onChange={(e) => setCustomScale(e.target.value)}
              placeholder="Altă scară"
              className="w-28 text-sm"
            />
          </div>
        </div>
      </div>

      {/* Mode + real unit picker */}
      <div className="flex flex-wrap gap-3 items-center">
        <div className="flex gap-2">
          <Button
            variant={mode === "real-to-drawing" ? "default" : "outline"}
            size="sm"
            onClick={() => { setMode("real-to-drawing"); setInputVal(""); }}
          >
            Real → Desen
          </Button>
          <Button
            variant={mode === "drawing-to-real" ? "default" : "outline"}
            size="sm"
            onClick={() => { setMode("drawing-to-real"); setInputVal(""); }}
          >
            Desen → Real
          </Button>
        </div>
        <div className="flex items-center gap-1.5">
          <span className="text-xs text-muted-foreground">Unitate reală:</span>
          {REAL_UNITS.map((u) => (
            <Button
              key={u.id}
              type="button"
              variant={realUnit === u.id ? "secondary" : "ghost"}
              size="sm"
              className="h-7 px-2 text-xs"
              onClick={() => { setRealUnit(u.id); setInputVal(""); }}
            >
              {u.label}
            </Button>
          ))}
        </div>
      </div>

      {/* Input */}
      <div>
        <Label>
          {mode === "real-to-drawing"
            ? `Dimensiune reală (${realUnit})`
            : "Dimensiune desen (mm)"}
        </Label>
        <div className="mt-1 flex gap-2 items-center">
          <Input
            type="number"
            min={0}
            step={realUnit === "km" ? 0.001 : realUnit === "m" ? 0.01 : 0.5}
            value={inputVal}
            onChange={(e) => setInputVal(e.target.value)}
            placeholder={
              mode === "real-to-drawing"
                ? realUnit === "m" ? "ex: 3.5" : realUnit === "km" ? "ex: 0.350" : "ex: 350"
                : "ex: 35"
            }
            className="flex-1"
          />
          <span className="text-sm text-muted-foreground shrink-0 w-8">
            {mode === "real-to-drawing" ? realUnit : "mm"}
          </span>
        </div>
      </div>

      {/* Result */}
      {!isNaN(val) && val > 0 && (
        <div className="rounded-md border bg-muted/30 p-4 space-y-2 text-sm">
          <p className="text-xs text-muted-foreground font-medium">Scară 1:{effectiveScale}</p>
          {mode === "real-to-drawing" ? (
            <>
              <p>
                Real:{" "}
                <strong>{fmt(val)} {realUnit}</strong>
                {realUnit !== "mm" && (
                  <span className="text-xs text-muted-foreground ml-2">
                    ({secondaryReal(real_mm)})
                  </span>
                )}
              </p>
              <p className="text-base border-t pt-2">
                Pe desen:{" "}
                <strong className="text-primary">{fmt(drawing_mm)} mm</strong>
                <CopyButton text={fmt(drawing_mm)} />
              </p>
              {!isNaN(drawing_mm) && (
                <p className="text-xs text-muted-foreground">
                  = {fmt(drawing_mm / 10)} cm pe desen
                </p>
              )}
            </>
          ) : (
            <>
              <p>
                Pe desen: <strong>{fmt(val)} mm</strong>
              </p>
              <p className="text-base border-t pt-2">
                Real:{" "}
                <strong className="text-primary">{fmt(real_in_unit)} {realUnit}</strong>
                <CopyButton text={fmt(real_in_unit)} />
              </p>
              {!isNaN(real_mm) && (
                <p className="text-xs text-muted-foreground">
                  {secondaryReal(real_mm)}
                </p>
              )}
            </>
          )}
        </div>
      )}
    </div>
  );
}

// ─── Main Module ──────────────────────────────────────────────────────────────

export function MiniUtilitiesModule() {
  return (
    <Tabs defaultValue="text-case" className="space-y-4">
      <div className="space-y-2">
        <TabsList className="flex h-auto flex-wrap gap-1 rounded-lg bg-muted/50 p-1">
          {/* ── Text & Calcule ── */}
          <TabsTrigger value="text-case">
            <Type className="mr-1.5 h-3.5 w-3.5" /> Text
          </TabsTrigger>
          <TabsTrigger value="char-count">
            <Hash className="mr-1.5 h-3.5 w-3.5" /> Caractere
          </TabsTrigger>
          <TabsTrigger value="num-to-text">
            <CaseUpper className="mr-1.5 h-3.5 w-3.5" /> Nr→Text
          </TabsTrigger>
          <TabsTrigger value="percentage">
            <Percent className="mr-1.5 h-3.5 w-3.5" /> Procente
          </TabsTrigger>
          <TabsTrigger value="tva">
            <Receipt className="mr-1.5 h-3.5 w-3.5" /> TVA
          </TabsTrigger>
          <TabsTrigger value="area">
            <Ruler className="mr-1.5 h-3.5 w-3.5" /> Suprafețe
          </TabsTrigger>
          <TabsTrigger value="u-value">
            <Zap className="mr-1.5 h-3.5 w-3.5" /> U↔R
          </TabsTrigger>
          <TabsTrigger value="thermal-compare">
            <Layers className="mr-1.5 h-3.5 w-3.5" /> Termică
          </TabsTrigger>
          <TabsTrigger value="mdlpa">
            <Building2 className="mr-1.5 h-3.5 w-3.5" /> MDLPA
          </TabsTrigger>
          <TabsTrigger value="scale">
            <Maximize2 className="mr-1.5 h-3.5 w-3.5" /> Scară
          </TabsTrigger>
        </TabsList>
        <TabsList className="flex h-auto flex-wrap gap-1 rounded-lg bg-muted/50 p-1">
          {/* ── Documente & Unelte ── */}
          <TabsTrigger value="pdf-reducer">
            <FileDown className="mr-1.5 h-3.5 w-3.5" /> Compresie PDF
          </TabsTrigger>
          <TabsTrigger value="pdf-unlock">
            <Unlock className="mr-1.5 h-3.5 w-3.5" /> Deblocare PDF
          </TabsTrigger>
          <TabsTrigger value="dwg-dxf">
            <PenTool className="mr-1.5 h-3.5 w-3.5" /> DWG→DXF
          </TabsTrigger>
          <TabsTrigger value="ocr">
            <ScanText className="mr-1.5 h-3.5 w-3.5" /> OCR
          </TabsTrigger>
          <TabsTrigger value="ai-cleaner">
            <Wand2 className="mr-1.5 h-3.5 w-3.5" /> Curățare AI
          </TabsTrigger>
          <TabsTrigger value="color-palette">
            <Palette className="mr-1.5 h-3.5 w-3.5" /> Culori
          </TabsTrigger>
        </TabsList>
      </div>

      <TabsContent value="text-case">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Transformare text</CardTitle>
          </CardHeader>
          <CardContent>
            <TextCaseConverter />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="char-count">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Numărare caractere</CardTitle>
          </CardHeader>
          <CardContent>
            <CharacterCounter />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="percentage">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Calculator procente</CardTitle>
          </CardHeader>
          <CardContent>
            <PercentageCalculator />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="tva">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Calculator TVA</CardTitle>
          </CardHeader>
          <CardContent>
            <TvaCalculator />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="area">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Convertor suprafețe</CardTitle>
          </CardHeader>
          <CardContent>
            <AreaConverter />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="u-value">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">
              Convertor U ↔ R (termoizolație)
            </CardTitle>
          </CardHeader>
          <CardContent>
            <UValueConverter />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="thermal-compare">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">
              Comparație termică materiale
            </CardTitle>
          </CardHeader>
          <CardContent>
            <MaterialThermalComparison />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="ai-cleaner">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Curățare text AI</CardTitle>
          </CardHeader>
          <CardContent>
            <AiArtifactCleaner />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="mdlpa">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">
              MDLPA — Date locale construcții
            </CardTitle>
          </CardHeader>
          <CardContent>
            <MdlpaValidator />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="pdf-reducer">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Reducere dimensiune PDF</CardTitle>
          </CardHeader>
          <CardContent>
            <PdfReducer />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="pdf-unlock">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Deblocare PDF</CardTitle>
          </CardHeader>
          <CardContent>
            <PdfUnlock />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="dwg-dxf">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Convertor DWG → DXF</CardTitle>
          </CardHeader>
          <CardContent>
            <DwgToDxf />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="ocr">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">
              OCR — extragere text din imagini
            </CardTitle>
          </CardHeader>
          <CardContent>
            <QuickOcr />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="num-to-text">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">
              Transformare numere în litere
            </CardTitle>
          </CardHeader>
          <CardContent>
            <NumberToText />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="color-palette">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Extractor paletă culori</CardTitle>
          </CardHeader>
          <CardContent>
            <ColorPaletteExtractor />
          </CardContent>
        </Card>
      </TabsContent>
      <TabsContent value="scale">
        <Card>
          <CardHeader>
            <CardTitle className="text-base">Calculator scară desen</CardTitle>
          </CardHeader>
          <CardContent>
            <ScaleCalculator />
          </CardContent>
        </Card>
      </TabsContent>
    </Tabs>
  );
}
