"use client";

import { useMemo, useState } from "react";
import { Button } from "@/components/ui/button";

function sortDeep(value: unknown): unknown {
  if (Array.isArray(value)) return value.map(sortDeep);
  if (value && typeof value === "object") {
    return Object.fromEntries(Object.entries(value as Record<string, unknown>).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => [k, sortDeep(v)]));
  }
  return value;
}

function errorLocation(input: string, message: string) {
  const match = message.match(/position (\d+)/i);
  if (!match) return "";
  const pos = Number(match[1]);
  const before = input.slice(0, pos);
  const line = before.split("\n").length;
  const col = before.length - before.lastIndexOf("\n");
  return ` Zeile ${line}, Spalte ${col}`;
}

export function JsonFormatter() {
  const [input, setInput] = useState('{"name":"Toolaro","tools":["JSON","QR-Code"]}');
  const [indent, setIndent] = useState(2);
  const [output, setOutput] = useState("");
  const [error, setError] = useState<string | null>(null);
  const lineNumbers = useMemo(() => input.split("\n").map((_, i) => i + 1).join("\n"), [input]);

  function run(mode: "format" | "minify" | "sort") {
    try {
      const parsed = JSON.parse(input);
      const value = mode === "sort" ? sortDeep(parsed) : parsed;
      setOutput(JSON.stringify(value, null, mode === "minify" ? 0 : indent));
      setError(null);
    } catch (err) {
      const msg = err instanceof Error ? err.message : "Ungültiges JSON";
      setError(`${msg}${errorLocation(input, msg)}`);
      setOutput("");
    }
  }

  function download() {
    const blob = new Blob([output || input], { type: "application/json" });
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = "toolaro.json";
    a.click();
  }

  return (
    <div className="space-y-5">
      <div className="overflow-hidden rounded-lg border">
        <div className="grid grid-cols-[44px_1fr]">
          <pre className="select-none bg-gray-50 p-3 text-right text-xs leading-6 text-gray-400">{lineNumbers}</pre>
          <textarea value={input} onChange={(e) => setInput(e.target.value)} className="min-h-[220px] resize-y p-3 font-mono text-sm leading-6 outline-none" />
        </div>
      </div>
      <div className="flex flex-wrap items-center gap-2">
        <select className="rounded-md border px-3 py-2 text-sm" value={indent} onChange={(e) => setIndent(Number(e.target.value))}>
          <option value={2}>2 Spaces</option>
          <option value={4}>4 Spaces</option>
        </select>
        <Button onClick={() => run("format")} disabled={!input}>Pretty Print</Button>
        <Button onClick={() => run("sort")} disabled={!input} variant="outline">Keys sortieren</Button>
        <Button onClick={() => run("minify")} disabled={!input} variant="outline">Minifizieren</Button>
        <Button onClick={() => navigator.clipboard.writeText(output)} disabled={!output} variant="outline">Kopieren</Button>
        <Button onClick={download} disabled={!output} variant="outline">Datei herunterladen</Button>
        <Button onClick={() => setInput('{"ok":true,"items":[1,2,3]}')} variant="outline">Beispiel einfügen</Button>
      </div>
      {error ? <p className="rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700">{error}</p> : output && <p className="rounded-lg border border-green-200 bg-green-50 p-3 text-sm text-green-700">JSON ist gültig.</p>}
      <pre className="min-h-[180px] overflow-auto rounded-lg border bg-gray-950 p-4 text-sm leading-6 text-blue-50">{output || "Noch kein Ergebnis."}</pre>
      <p className="rounded-lg border border-blue-100 bg-blue-50 p-3 text-sm leading-6 text-blue-950">Premium: größere Dateien, Batch-Validierung und gespeicherte Format-Vorgaben sind vorbereitet.</p>
    </div>
  );
}
