import { useEffect, useRef, useState } from "react";
import { toast } from "sonner";
import { GenericTool } from "./GenericTool";
import type { ToolKind } from "@/lib/tools";

const nbtEscape = (s: string) => s.replace(/'/g, "\\'");

/* ---------------- CUSTOM tools ---------------- */

function ProfilePicture() {
  const [name, setName] = useState("Notch");
  const [type, setType] = useState<"avatar" | "head" | "body" | "bust">("avatar");
  const url = `https://mc-heads.net/${type}/${encodeURIComponent(name || "steve")}/256`;
  return (
    <div className="grid gap-4 md:grid-cols-[1fr_260px]">
      <div className="space-y-3">
        <div>
          <label className="text-xs pixel" style={{ fontSize: 10 }}>NICK OU UUID</label>
          <input className="w-full rounded-md bg-input border border-border p-2 mono" value={name} onChange={(e) => setName(e.target.value)} placeholder="ex: Dream" />
        </div>
        <div>
          <label className="text-xs pixel" style={{ fontSize: 10 }}>ESTILO</label>
          <select className="w-full rounded-md bg-input border border-border p-2" value={type} onChange={(e) => setType(e.target.value as "avatar" | "head" | "body" | "bust")}>
            <option value="avatar">Avatar 2D</option>
            <option value="head">Cabeça 3D</option>
            <option value="bust">Busto 3D</option>
            <option value="body">Corpo inteiro 3D</option>
          </select>
        </div>
        <a href={url} download={`${name}-${type}.png`} target="_blank" rel="noreferrer" className="mc-btn mc-btn-hover inline-block rounded-md">Baixar PNG</a>
        <p className="text-xs text-muted-foreground">Serviço público mc-heads.net · sem armazenamento no site.</p>
      </div>
      <div className="mc-card rounded-md p-3 flex items-center justify-center min-h-72">
        <img src={url} alt={`${name} ${type}`} className="max-h-72" style={{ imageRendering: "pixelated" }} />
      </div>
    </div>
  );
}

function SkinViewer() {
  const [name, setName] = useState("Notch");
  return (
    <div className="grid gap-4 md:grid-cols-[1fr_260px]">
      <div className="space-y-3">
        <input className="w-full rounded-md bg-input border border-border p-2 mono" value={name} onChange={(e) => setName(e.target.value)} placeholder="Nick" />
        <a className="mc-btn mc-btn-hover inline-block rounded-md" href={`https://mc-heads.net/skin/${name}`} target="_blank" rel="noreferrer" download>Baixar Skin (PNG)</a>
      </div>
      <div className="mc-card rounded-md p-3 flex items-center justify-center min-h-72">
        <img src={`https://mc-heads.net/body/${name}/512`} alt="body" style={{ imageRendering: "pixelated" }} className="max-h-72" />
      </div>
    </div>
  );
}

function ServerStatus() {
  const [host, setHost] = useState("hypixel.net");
  const [data, setData] = useState<Record<string, unknown> | null>(null);
  const [loading, setLoading] = useState(false);
  const check = async () => {
    setLoading(true);
    try {
      const r = await fetch(`https://api.mcsrvstat.us/3/${host}`);
      setData(await r.json());
    } catch { toast.error("Falha na consulta"); } finally { setLoading(false); }
  };
  return (
    <div className="space-y-3">
      <div className="flex gap-2">
        <input className="flex-1 rounded-md bg-input border border-border p-2 mono" value={host} onChange={(e) => setHost(e.target.value)} placeholder="ex: mc.hypixel.net" />
        <button onClick={check} className="mc-btn mc-btn-hover rounded-md">{loading ? "..." : "Consultar"}</button>
      </div>
      {data && (
        <pre className="mc-card rounded-md p-3 mono text-xs overflow-auto max-h-96">{JSON.stringify(data, null, 2)}</pre>
      )}
      <p className="text-xs text-muted-foreground">Fonte: api.mcsrvstat.us (público).</p>
    </div>
  );
}

const COLOR_CODES: Array<[string, string, string]> = [
  ["§0", "#000000", "Preto"], ["§1", "#0000AA", "Azul Escuro"], ["§2", "#00AA00", "Verde Escuro"],
  ["§3", "#00AAAA", "Aqua Escuro"], ["§4", "#AA0000", "Vermelho Escuro"], ["§5", "#AA00AA", "Roxo"],
  ["§6", "#FFAA00", "Dourado"], ["§7", "#AAAAAA", "Cinza"], ["§8", "#555555", "Cinza Escuro"],
  ["§9", "#5555FF", "Azul"], ["§a", "#55FF55", "Verde"], ["§b", "#55FFFF", "Aqua"],
  ["§c", "#FF5555", "Vermelho"], ["§d", "#FF55FF", "Magenta"], ["§e", "#FFFF55", "Amarelo"],
  ["§f", "#FFFFFF", "Branco"], ["§k", "#888", "Obfuscado"], ["§l", "#888", "Negrito"],
  ["§m", "#888", "Riscado"], ["§n", "#888", "Sublinhado"], ["§o", "#888", "Itálico"], ["§r", "#888", "Reset"],
];

function ColorCodes() {
  return (
    <div className="grid grid-cols-2 md:grid-cols-3 gap-2">
      {COLOR_CODES.map(([code, hex, name]) => (
        <button key={code} onClick={() => { navigator.clipboard.writeText(code); toast.success(`Copiado ${code}`); }}
          className="mc-card rounded-md p-3 text-left hover:brightness-125 transition">
          <div className="flex items-center gap-2">
            <span className="w-6 h-6 rounded" style={{ background: hex }} />
            <span className="mono text-sm">{code}</span>
          </div>
          <div className="text-xs text-muted-foreground mt-1">{name}</div>
        </button>
      ))}
    </div>
  );
}

function GradientText() {
  const [text, setText] = useState("C0DSXS");
  const [from, setFrom] = useState("#55FFFF");
  const [to, setTo] = useState("#FF55FF");
  const hexInterp = (a: string, b: string, t: number) => {
    const p = (h: string) => [1, 3, 5].map((i) => parseInt(h.slice(i, i + 2), 16));
    const [r1, g1, b1] = p(a); const [r2, g2, b2] = p(b);
    const mix = (x: number, y: number) => Math.round(x + (y - x) * t).toString(16).padStart(2, "0");
    return `${mix(r1, r2)}${mix(g1, g2)}${mix(b1, b2)}`;
  };
  const out = [...text].map((ch, i, arr) => {
    const t = arr.length <= 1 ? 0 : i / (arr.length - 1);
    return `§x§${hexInterp(from, to, t).split("").map((c) => "§" + c).join("")}${ch}`;
  }).join("");
  return (
    <div className="space-y-3">
      <input className="w-full rounded-md bg-input border border-border p-2 mono" value={text} onChange={(e) => setText(e.target.value)} />
      <div className="flex gap-2">
        <input type="color" value={from} onChange={(e) => setFrom(e.target.value)} className="h-10 w-16 rounded-md bg-input" />
        <input type="color" value={to} onChange={(e) => setTo(e.target.value)} className="h-10 w-16 rounded-md bg-input" />
      </div>
      <div className="mc-card rounded-md p-4 text-2xl mono flex flex-wrap">
        {[...text].map((ch, i, arr) => {
          const t = arr.length <= 1 ? 0 : i / (arr.length - 1);
          return <span key={i} style={{ color: `#${hexInterp(from, to, t)}` }}>{ch}</span>;
        })}
      </div>
      <div className="flex items-center justify-between">
        <span className="text-xs text-muted-foreground pixel" style={{ fontSize: 10 }}>Bungee / Spigot</span>
        <button onClick={() => { navigator.clipboard.writeText(out); toast.success("Copiado!"); }} className="mc-btn mc-btn-hover rounded-md">Copiar</button>
      </div>
      <pre className="mc-card rounded-md p-3 mono text-xs whitespace-pre-wrap break-all">{out}</pre>
    </div>
  );
}

function TextureEditor() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [color, setColor] = useState("#55FF55");
  const [size, setSize] = useState(16);
  const cell = 20;
  useEffect(() => {
    const c = canvasRef.current!; const ctx = c.getContext("2d")!;
    ctx.fillStyle = "#00000000"; ctx.clearRect(0, 0, c.width, c.height);
    ctx.strokeStyle = "#333";
    for (let i = 0; i <= size; i++) {
      ctx.beginPath(); ctx.moveTo(i * cell, 0); ctx.lineTo(i * cell, size * cell); ctx.stroke();
      ctx.beginPath(); ctx.moveTo(0, i * cell); ctx.lineTo(size * cell, i * cell); ctx.stroke();
    }
  }, [size]);
  const paint = (e: React.MouseEvent<HTMLCanvasElement>) => {
    const c = canvasRef.current!; const rect = c.getBoundingClientRect();
    const x = Math.floor(((e.clientX - rect.left) / rect.width) * size);
    const y = Math.floor(((e.clientY - rect.top) / rect.height) * size);
    const ctx = c.getContext("2d")!; ctx.fillStyle = color; ctx.fillRect(x * cell, y * cell, cell, cell);
  };
  const exportPng = () => {
    const c = canvasRef.current!;
    const off = document.createElement("canvas"); off.width = size; off.height = size;
    const octx = off.getContext("2d")!;
    octx.drawImage(c, 0, 0, size * cell, size * cell, 0, 0, size, size);
    const a = document.createElement("a"); a.href = off.toDataURL("image/png"); a.download = `texture-${size}x${size}.png`; a.click();
  };
  return (
    <div className="space-y-3">
      <div className="flex flex-wrap gap-2 items-center">
        <input type="color" value={color} onChange={(e) => setColor(e.target.value)} className="h-10 w-16 rounded-md bg-input" />
        <select value={size} onChange={(e) => setSize(+e.target.value)} className="rounded-md bg-input border border-border p-2">
          {[8, 16, 32].map((n) => <option key={n} value={n}>{n}×{n}</option>)}
        </select>
        <button onClick={exportPng} className="mc-btn mc-btn-hover rounded-md">Baixar PNG</button>
      </div>
      <canvas
        ref={canvasRef}
        width={size * cell}
        height={size * cell}
        onMouseDown={paint}
        onMouseMove={(e) => e.buttons === 1 && paint(e)}
        className="mc-card rounded-md cursor-crosshair"
        style={{ imageRendering: "pixelated" }}
      />
    </div>
  );
}

/* --------------- OUTPUT-based tools --------------- */

const CMD_BUILDERS: Partial<Record<ToolKind, () => React.ReactElement>> = {
  "command-give": () => (
    <GenericTool
      fields={[
        { name: "player", label: "Jogador", type: "text", default: "@p" },
        { name: "item", label: "Item", type: "text", default: "minecraft:diamond_sword" },
        { name: "count", label: "Quantidade", type: "number", default: "1" },
        { name: "nbt", label: "NBT (opcional)", type: "textarea", default: "{Enchantments:[{id:\"minecraft:sharpness\",lvl:10}]}", placeholder: "{ ... }" },
      ]}
      build={(v) => `/give ${v.player} ${v.item}${v.nbt ? v.nbt : ""} ${v.count}`}
    />
  ),
  "command-summon": () => (
    <GenericTool
      fields={[
        { name: "entity", label: "Entidade", type: "text", default: "minecraft:zombie" },
        { name: "pos", label: "Posição", type: "text", default: "~ ~ ~" },
        { name: "nbt", label: "NBT", type: "textarea", default: "{CustomName:'{\"text\":\"Boss\"}',IsBaby:0b}" },
      ]}
      build={(v) => `/summon ${v.entity} ${v.pos} ${v.nbt || ""}`.trim()}
    />
  ),
  "command-tellraw": () => (
    <GenericTool
      fields={[
        { name: "target", label: "Alvo", type: "text", default: "@a" },
        { name: "text", label: "Texto", type: "textarea", default: "Bem-vindo!" },
        { name: "color", label: "Cor", type: "select", options: ["white", "red", "green", "aqua", "gold", "light_purple", "yellow"], default: "gold" },
        { name: "bold", label: "Negrito", type: "select", options: ["false", "true"], default: "false" },
      ]}
      build={(v) => `/tellraw ${v.target} ${JSON.stringify({ text: v.text, color: v.color, bold: v.bold === "true" })}`}
    />
  ),
  "command-tp": () => (
    <GenericTool
      fields={[
        { name: "target", label: "Alvo", type: "text", default: "@p" },
        { name: "dest", label: "Destino / Coord", type: "text", default: "0 100 0" },
      ]}
      build={(v) => `/tp ${v.target} ${v.dest}`}
    />
  ),
  "command-title": () => (
    <GenericTool
      fields={[
        { name: "target", label: "Alvo", type: "text", default: "@a" },
        { name: "title", label: "Título", type: "text", default: "Bem-vindo" },
        { name: "sub", label: "Subtítulo", type: "text", default: "ao servidor" },
        { name: "color", label: "Cor", type: "select", options: ["white", "red", "green", "aqua", "gold", "yellow"], default: "gold" },
      ]}
      build={(v) =>
        `/title ${v.target} title ${JSON.stringify({ text: v.title, color: v.color })}\n/title ${v.target} subtitle ${JSON.stringify({ text: v.sub })}`}
    />
  ),
  "command-effect": () => (
    <GenericTool
      fields={[
        { name: "target", label: "Alvo", type: "text", default: "@p" },
        { name: "effect", label: "Efeito", type: "text", default: "minecraft:speed" },
        { name: "seconds", label: "Duração (s)", type: "number", default: "60" },
        { name: "amp", label: "Nível", type: "number", default: "1" },
        { name: "hide", label: "Ocultar partículas", type: "select", options: ["false", "true"], default: "true" },
      ]}
      build={(v) => `/effect give ${v.target} ${v.effect} ${v.seconds} ${v.amp} ${v.hide}`}
    />
  ),
  "command-fill": () => (
    <GenericTool
      fields={[
        { name: "from", label: "De (x y z)", type: "text", default: "~-5 ~ ~-5" },
        { name: "to", label: "Até (x y z)", type: "text", default: "~5 ~5 ~5" },
        { name: "block", label: "Bloco", type: "text", default: "minecraft:stone" },
        { name: "mode", label: "Modo", type: "select", options: ["replace", "keep", "hollow", "outline", "destroy"], default: "replace" },
      ]}
      build={(v) => `/fill ${v.from} ${v.to} ${v.block} ${v.mode}`}
    />
  ),
  "command-clone": () => (
    <GenericTool
      fields={[
        { name: "from", label: "De", type: "text", default: "~-5 ~ ~-5" },
        { name: "to", label: "Até", type: "text", default: "~5 ~5 ~5" },
        { name: "dest", label: "Destino", type: "text", default: "~10 ~ ~" },
      ]}
      build={(v) => `/clone ${v.from} ${v.to} ${v.dest}`}
    />
  ),
  "command-setblock": () => (
    <GenericTool
      fields={[
        { name: "pos", label: "Posição", type: "text", default: "~ ~ ~" },
        { name: "block", label: "Bloco", type: "text", default: "minecraft:redstone_block" },
      ]}
      build={(v) => `/setblock ${v.pos} ${v.block}`}
    />
  ),
  "command-playsound": () => (
    <GenericTool
      fields={[
        { name: "sound", label: "Som", type: "text", default: "minecraft:entity.experience_orb.pickup" },
        { name: "source", label: "Categoria", type: "select", options: ["master", "music", "record", "weather", "block", "hostile", "neutral", "player", "ambient", "voice"], default: "master" },
        { name: "target", label: "Alvo", type: "text", default: "@a" },
        { name: "vol", label: "Volume", type: "number", default: "1" },
        { name: "pitch", label: "Pitch", type: "number", default: "1" },
      ]}
      build={(v) => `/playsound ${v.sound} ${v.source} ${v.target} ~ ~ ~ ${v.vol} ${v.pitch}`}
    />
  ),
  "command-particle": () => (
    <GenericTool
      fields={[
        { name: "particle", label: "Partícula", type: "text", default: "minecraft:flame" },
        { name: "pos", label: "Posição", type: "text", default: "~ ~1 ~" },
        { name: "count", label: "Quantidade", type: "number", default: "50" },
      ]}
      build={(v) => `/particle ${v.particle} ${v.pos} 0.3 0.3 0.3 0.05 ${v.count}`}
    />
  ),
  "command-firework": () => (
    <GenericTool
      fields={[
        { name: "shape", label: "Formato", type: "select", options: ["0", "1", "2", "3", "4"], default: "1", hint: "0=pequeno,1=grande,2=estrela,3=criador,4=explosão" },
        { name: "color", label: "Cor (dec)", type: "number", default: "16777215", hint: "RGB decimal ex 16777215=branco" },
        { name: "flight", label: "Duração voo", type: "number", default: "2" },
      ]}
      build={(v) => `/summon firework_rocket ~ ~ ~ {FireworksItem:{id:firework_rocket,Count:1,tag:{Fireworks:{Flight:${v.flight}b,Explosions:[{Type:${v.shape}b,Colors:[I;${v.color}]}]}}}}`}
    />
  ),
  "enchantment-builder": () => (
    <GenericTool
      fields={[
        { name: "item", label: "Item", type: "text", default: "minecraft:netherite_sword" },
        { name: "ench", label: "Encantamentos (id:nível, ...)", type: "textarea", default: "sharpness:10, unbreaking:5, fire_aspect:3" },
      ]}
      build={(v) => {
        const list = v.ench.split(",").map((s) => s.trim()).filter(Boolean)
          .map((p) => { const [id, lvl] = p.split(":"); return `{id:"minecraft:${id.trim()}",lvl:${lvl?.trim() || 1}}`; }).join(",");
        return `/give @p ${v.item}{Enchantments:[${list}]} 1`;
      }}
    />
  ),
  "potion-builder": () => (
    <GenericTool
      fields={[
        { name: "effect", label: "Efeito", type: "text", default: "minecraft:strength" },
        { name: "dur", label: "Duração (ticks)", type: "number", default: "3600" },
        { name: "amp", label: "Nível", type: "number", default: "2" },
        { name: "name", label: "Nome", type: "text", default: "Poção do C0DSXS" },
      ]}
      build={(v) => `/give @p potion{CustomPotionEffects:[{Id:${effectId(v.effect)},Duration:${v.dur},Amplifier:${v.amp}}],display:{Name:'${nbtEscape(JSON.stringify({ text: v.name, color: "light_purple" }))}'}} 1`}
    />
  ),
  "attribute-builder": () => (
    <GenericTool
      fields={[
        { name: "attr", label: "Atributo", type: "select", options: ["generic.max_health", "generic.attack_damage", "generic.movement_speed", "generic.armor", "generic.knockback_resistance"], default: "generic.attack_damage" },
        { name: "amount", label: "Valor", type: "number", default: "10" },
        { name: "op", label: "Operação", type: "select", options: ["0", "1", "2"], default: "0", hint: "0=add, 1=multiply_base, 2=multiply" },
      ]}
      build={(v) => `/attribute @p ${v.attr} modifier add 00000000-0000-0000-0000-000000000001 "codsxs" ${v.amount} ${v.op === "0" ? "add" : v.op === "1" ? "multiply_base" : "multiply"}`}
    />
  ),
};

function effectId(id: string) {
  const map: Record<string, number> = { speed: 1, slowness: 2, haste: 3, mining_fatigue: 4, strength: 5, jump_boost: 8, regeneration: 10, resistance: 11, fire_resistance: 12, water_breathing: 13, invisibility: 14, night_vision: 16, weakness: 18, poison: 19, wither: 20 };
  const key = id.replace("minecraft:", "");
  return map[key] ?? 1;
}

/* --------------- SCAFFOLD / MERGER (JSZip) --------------- */

async function makeZipFromMap(files: Record<string, string | Blob>): Promise<Blob> {
  const JSZip = (await import("jszip")).default;
  const zip = new JSZip();
  for (const [path, content] of Object.entries(files)) zip.file(path, content);
  return zip.generateAsync({ type: "blob" });
}

function downloadBlob(blob: Blob, name: string) {
  const a = document.createElement("a"); a.href = URL.createObjectURL(blob); a.download = name; a.click();
}

function DatapackScaffold() {
  const [name, setName] = useState("meu_datapack");
  const [ns, setNs] = useState("codsxs");
  const [desc, setDesc] = useState("Datapack criado com C0DSXS");
  const build = async () => {
    const blob = await makeZipFromMap({
      "pack.mcmeta": JSON.stringify({ pack: { pack_format: 48, description: desc } }, null, 2),
      [`data/${ns}/functions/tick.mcfunction`]: `# tick function\nsay ${name} carregado`,
      [`data/${ns}/functions/load.mcfunction`]: `tellraw @a {"text":"[${name}] carregado","color":"green"}`,
      "data/minecraft/tags/functions/tick.json": JSON.stringify({ values: [`${ns}:tick`] }, null, 2),
      "data/minecraft/tags/functions/load.json": JSON.stringify({ values: [`${ns}:load`] }, null, 2),
      "CREDITS.txt": `Gerado com C0DSXS — https://github.com/`,
    });
    downloadBlob(blob, `${name}.zip`);
  };
  return (
    <div className="space-y-3">
      <input className="w-full rounded-md bg-input border border-border p-2 mono" value={name} onChange={(e) => setName(e.target.value)} placeholder="Nome do datapack" />
      <input className="w-full rounded-md bg-input border border-border p-2 mono" value={ns} onChange={(e) => setNs(e.target.value)} placeholder="namespace" />
      <input className="w-full rounded-md bg-input border border-border p-2 mono" value={desc} onChange={(e) => setDesc(e.target.value)} placeholder="Descrição" />
      <button onClick={build} className="mc-btn mc-btn-hover rounded-md">Gerar Datapack .zip</button>
    </div>
  );
}

function ResourcePackScaffold() {
  const [name, setName] = useState("meu_resourcepack");
  const [desc, setDesc] = useState("Resource pack criado com C0DSXS");
  const build = async () => {
    const blob = await makeZipFromMap({
      "pack.mcmeta": JSON.stringify({ pack: { pack_format: 34, description: desc } }, null, 2),
      "assets/minecraft/lang/en_us.json": JSON.stringify({}, null, 2),
      "assets/minecraft/textures/README.txt": "Coloque texturas aqui.",
      "CREDITS.txt": "Gerado com C0DSXS",
    });
    downloadBlob(blob, `${name}.zip`);
  };
  return (
    <div className="space-y-3">
      <input className="w-full rounded-md bg-input border border-border p-2 mono" value={name} onChange={(e) => setName(e.target.value)} />
      <input className="w-full rounded-md bg-input border border-border p-2 mono" value={desc} onChange={(e) => setDesc(e.target.value)} />
      <button onClick={build} className="mc-btn mc-btn-hover rounded-md">Gerar Resource Pack .zip</button>
    </div>
  );
}

function BedrockPackScaffold() {
  const [name, setName] = useState("meu_addon");
  const uuid = () => crypto.randomUUID();
  const build = async () => {
    const bpUuid = uuid(), rpUuid = uuid();
    const blob = await makeZipFromMap({
      [`${name}_BP/manifest.json`]: JSON.stringify({ format_version: 2, header: { name, description: "C0DSXS BP", uuid: bpUuid, version: [1, 0, 0], min_engine_version: [1, 20, 0] }, modules: [{ type: "data", uuid: uuid(), version: [1, 0, 0] }] }, null, 2),
      [`${name}_RP/manifest.json`]: JSON.stringify({ format_version: 2, header: { name, description: "C0DSXS RP", uuid: rpUuid, version: [1, 0, 0], min_engine_version: [1, 20, 0] }, modules: [{ type: "resources", uuid: uuid(), version: [1, 0, 0] }] }, null, 2),
      "CREDITS.txt": "Gerado com C0DSXS",
    });
    downloadBlob(blob, `${name}.mcaddon.zip`);
  };
  return (
    <div className="space-y-3">
      <input className="w-full rounded-md bg-input border border-border p-2 mono" value={name} onChange={(e) => setName(e.target.value)} />
      <button onClick={build} className="mc-btn mc-btn-hover rounded-md">Gerar Add-on Bedrock .zip</button>
    </div>
  );
}

function ModpackManifest() {
  const [name, setName] = useState("Meu Modpack");
  const [author, setAuthor] = useState("C0DSXS");
  const [version, setVersion] = useState("1.0.0");
  const [mcVersion, setMcVersion] = useState("1.20.1");
  const [loader, setLoader] = useState("forge-47.2.0");
  const [projects, setProjects] = useState("238222:5000000\n306612:4900000");
  const build = async () => {
    const files = projects.split("\n").filter(Boolean).map((l) => {
      const [projectID, fileID] = l.split(":").map((s) => parseInt(s.trim(), 10));
      return { projectID, fileID, required: true };
    });
    const manifest = { minecraft: { version: mcVersion, modLoaders: [{ id: loader, primary: true }] }, manifestType: "minecraftModpack", manifestVersion: 1, name, version, author, files, overrides: "overrides" };
    const blob = await makeZipFromMap({ "manifest.json": JSON.stringify(manifest, null, 2), "modlist.html": `<h1>${name}</h1><p>Gerado por C0DSXS</p>`, "overrides/README.txt": "Coloque configs e mods extras aqui.", "CREDITS.txt": "Gerado com C0DSXS" });
    downloadBlob(blob, `${name.replace(/\s+/g, "_")}-modpack.zip`);
  };
  return (
    <div className="space-y-2">
      <input className="w-full rounded-md bg-input border border-border p-2" value={name} onChange={(e) => setName(e.target.value)} placeholder="Nome" />
      <input className="w-full rounded-md bg-input border border-border p-2" value={author} onChange={(e) => setAuthor(e.target.value)} placeholder="Autor" />
      <input className="w-full rounded-md bg-input border border-border p-2" value={version} onChange={(e) => setVersion(e.target.value)} placeholder="Versão" />
      <input className="w-full rounded-md bg-input border border-border p-2" value={mcVersion} onChange={(e) => setMcVersion(e.target.value)} placeholder="Versão MC" />
      <input className="w-full rounded-md bg-input border border-border p-2 mono" value={loader} onChange={(e) => setLoader(e.target.value)} placeholder="Loader ex: forge-47.2.0 / neoforge-20.4.196 / fabric-0.15.0" />
      <textarea className="w-full rounded-md bg-input border border-border p-2 mono min-h-28" value={projects} onChange={(e) => setProjects(e.target.value)} placeholder="projectID:fileID (uma por linha)" />
      <button onClick={build} className="mc-btn mc-btn-hover rounded-md">Gerar manifest.json (.zip)</button>
    </div>
  );
}

function PackMerger({ kind }: { kind: "resource" | "data" }) {
  const [files, setFiles] = useState<File[]>([]);
  const [busy, setBusy] = useState(false);
  const merge = async () => {
    if (!files.length) return toast.error("Selecione ao menos um .zip");
    setBusy(true);
    try {
      const JSZip = (await import("jszip")).default;
      const out = new JSZip();
      for (const file of files) {
        const z = await JSZip.loadAsync(file);
        const entries = Object.entries(z.files);
        for (const [path, entry] of entries) {
          if ((entry as { dir: boolean }).dir) continue;
          const content = await (entry as { async: (t: string) => Promise<Uint8Array> }).async("uint8array");
          out.file(path, content);
        }
      }
      out.file("CREDITS.txt", `Merge gerado pelo C0DSXS a partir de ${files.length} pack(s).\nDê crédito aos autores originais.`);
      const blob = await out.generateAsync({ type: "blob" });
      downloadBlob(blob, `${kind === "resource" ? "resourcepack" : "datapack"}-merged.zip`);
      toast.success("Merge concluído");
    } catch (e) { toast.error((e as Error).message); } finally { setBusy(false); }
  };
  return (
    <div className="space-y-3">
      <input type="file" accept=".zip" multiple onChange={(e) => setFiles(Array.from(e.target.files ?? []))} className="w-full rounded-md bg-input border border-border p-2" />
      {files.length > 0 && (<ul className="text-xs text-muted-foreground list-disc pl-5">{files.map((f) => <li key={f.name}>{f.name}</li>)}</ul>)}
      <button onClick={merge} disabled={busy} className="mc-btn mc-btn-hover rounded-md">{busy ? "Processando..." : "Juntar e Baixar"}</button>
      <p className="text-xs text-muted-foreground">Arquivos posteriores sobrescrevem anteriores em caso de conflito. Sempre dê crédito aos autores originais dos packs.</p>
    </div>
  );
}

/* --------------- Simple text/output generators --------------- */

function CoordNether() {
  const [x, setX] = useState("100"); const [z, setZ] = useState("-40"); const [dir, setDir] = useState<"ow2nether" | "nether2ow">("ow2nether");
  const nx = dir === "ow2nether" ? Math.round(+x / 8) : +x * 8;
  const nz = dir === "ow2nether" ? Math.round(+z / 8) : +z * 8;
  return (
    <div className="space-y-3">
      <select className="rounded-md bg-input border border-border p-2" value={dir} onChange={(e) => setDir(e.target.value as "ow2nether" | "nether2ow")}>
        <option value="ow2nether">Overworld → Nether</option>
        <option value="nether2ow">Nether → Overworld</option>
      </select>
      <div className="flex gap-2">
        <input className="flex-1 rounded-md bg-input border border-border p-2 mono" value={x} onChange={(e) => setX(e.target.value)} placeholder="X" />
        <input className="flex-1 rounded-md bg-input border border-border p-2 mono" value={z} onChange={(e) => setZ(e.target.value)} placeholder="Z" />
      </div>
      <div className="mc-card rounded-md p-4 mono">→ X: {nx} · Z: {nz}</div>
    </div>
  );
}

function XpCalculator() {
  const [lvl, setLvl] = useState("30");
  const pointsForLevel = (L: number) => L <= 16 ? L * L + 6 * L : L <= 31 ? 2.5 * L * L - 40.5 * L + 360 : 4.5 * L * L - 162.5 * L + 2220;
  const total = Math.round(pointsForLevel(+lvl || 0));
  return (
    <div className="space-y-3">
      <input type="number" className="w-full rounded-md bg-input border border-border p-2 mono" value={lvl} onChange={(e) => setLvl(e.target.value)} />
      <div className="mc-card rounded-md p-4 mono">Nível {lvl} = <b>{total}</b> pontos totais de XP</div>
    </div>
  );
}

function RandomLoot() {
  const [count, setCount] = useState("5");
  const items = ["diamond", "iron_ingot", "gold_ingot", "emerald", "netherite_scrap", "enchanted_book", "golden_apple", "totem_of_undying", "ender_pearl", "elytra"];
  const roll = () => Array.from({ length: +count || 0 }, () => items[Math.floor(Math.random() * items.length)]).join("\n");
  const [out, setOut] = useState(roll);
  return (
    <div className="space-y-3">
      <input type="number" className="w-full rounded-md bg-input border border-border p-2 mono" value={count} onChange={(e) => setCount(e.target.value)} />
      <button className="mc-btn mc-btn-hover rounded-md" onClick={() => setOut(roll())}>Rolar</button>
      <pre className="mc-card rounded-md p-3 mono text-sm whitespace-pre-wrap">{out}</pre>
    </div>
  );
}

function NameGen({ pool }: { pool: string[][] }) {
  const gen = () => pool.map((p) => p[Math.floor(Math.random() * p.length)]).join("");
  const [names, setNames] = useState<string[]>(() => Array.from({ length: 8 }, gen));
  return (
    <div className="space-y-3">
      <button onClick={() => setNames(Array.from({ length: 8 }, gen))} className="mc-btn mc-btn-hover rounded-md">Gerar mais</button>
      <ul className="grid grid-cols-2 gap-2">
        {names.map((n, i) => (
          <li key={i} className="mc-card rounded-md p-2 mono flex items-center justify-between">
            <span>{n}</span>
            <button className="text-xs text-primary" onClick={() => { navigator.clipboard.writeText(n); toast.success("Copiado"); }}>copiar</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

/* --------------- ROUTER --------------- */

export function ToolPanel({ kind }: { kind: ToolKind }) {
  if (kind === "profile-picture") return <ProfilePicture />;
  if (kind === "skin-viewer") return <SkinViewer />;
  if (kind === "uuid-lookup") return (
    <GenericTool
      fields={[{ name: "user", label: "Nick", type: "text", default: "Notch" }]}
      build={(v) => `Página do jogador:\nhttps://namemc.com/profile/${v.user}\n\nAvatar:\nhttps://mc-heads.net/avatar/${v.user}`}
      language="text"
    />
  );
  if (kind === "server-status") return <ServerStatus />;
  if (kind === "server-motd") return (
    <GenericTool
      fields={[
        { name: "line1", label: "Linha 1", type: "text", default: "§b§lMeu Servidor" },
        { name: "line2", label: "Linha 2", type: "text", default: "§eBem-vindo!" },
      ]}
      build={(v) => `motd=${v.line1}\\n${v.line2}`}
      language="server.properties"
    />
  );
  if (kind === "gradient-motd" || kind === "gradient-text") return <GradientText />;
  if (kind === "color-codes") return <ColorCodes />;
  if (kind === "coord-nether") return <CoordNether />;
  if (kind === "xp-calculator") return <XpCalculator />;
  if (kind === "texture-editor") return <TextureEditor />;
  if (kind === "random-loot") return <RandomLoot />;
  if (kind === "datapack-scaffold") return <DatapackScaffold />;
  if (kind === "resourcepack-scaffold") return <ResourcePackScaffold />;
  if (kind === "bedrockpack-scaffold") return <BedrockPackScaffold />;
  if (kind === "modpack-manifest") return <ModpackManifest />;
  if (kind === "pack-merger") return <PackMerger kind="resource" />;
  if (kind === "datapack-merger") return <PackMerger kind="data" />;

  if (kind === "player-name-gen") return <NameGen pool={[["Sha", "Kro", "Ender", "Void", "Nether", "Sky", "Redstone", "Diamond"], ["dow", "flame", "night", "byte", "gg", "MC", "Boy", "Girl", "X"], ["", "_", "99", "42", "YT"]]} />;
  if (kind === "village-name-gen") return <NameGen pool={[["Old", "New", "Wolf", "Ash", "Iron", "Sun", "Moon"], [""], ["haven", "burg", "wood", "stead", "brook", "vale", "spire"]]} />;
  if (kind === "server-name-gen") return <NameGen pool={[["Cube", "Nether", "Craft", "Pixel", "Aether", "Void", "Ender", "Redstone"], ["Craft", "MC", "Realms", "World", "Legends", "Kingdom", "Nation", "SMP"]]} />;

  if (kind === "player-head-give") return <GenericTool fields={[{ name: "user", label: "Nick", type: "text", default: "Notch" }]} build={(v) => `/give @p minecraft:player_head{SkullOwner:"${v.user}"} 1`} />;
  if (kind === "sign-generator") return <GenericTool fields={[
    { name: "l1", label: "Linha 1", type: "text", default: "§6Bem-vindo" },
    { name: "l2", label: "Linha 2", type: "text", default: "§rao servidor" },
    { name: "l3", label: "Linha 3", type: "text", default: "" },
    { name: "l4", label: "Linha 4", type: "text", default: "§7C0DSXS" },
  ]} build={(v) => `/setblock ~ ~ ~ minecraft:oak_sign{front_text:{messages:[${[v.l1,v.l2,v.l3,v.l4].map(l=>JSON.stringify({text:l})).join(",")}]}}`} />;

  if (kind === "book-writer") return <GenericTool fields={[
    { name: "title", label: "Título", type: "text", default: "Meu Livro" },
    { name: "author", label: "Autor", type: "text", default: "C0DSXS" },
    { name: "pages", label: "Páginas (uma por linha)", type: "textarea", default: "Página 1\nPágina 2" },
  ]} build={(v) => {
    const pages = v.pages.split("\n").map((p) => `'${JSON.stringify({ text: p }).replace(/'/g, "\\'")}'`).join(",");
    return `/give @p written_book{title:"${v.title}",author:"${v.author}",pages:[${pages}]} 1`;
  }} />;

  if (kind === "text-obfuscator") return <GenericTool fields={[{ name: "t", label: "Texto", type: "text", default: "SEGREDO" }]} build={(v) => `§k${v.t}§r`} />;
  if (kind === "json-nbt-pretty") return <GenericTool fields={[{ name: "j", label: "JSON", type: "textarea", default: '{"a":1,"b":[1,2,3]}' }]} build={(v) => { try { return JSON.stringify(JSON.parse(v.j), null, 2); } catch { return "// JSON inválido"; } }} />;

  if (kind === "server-properties") return <GenericTool fields={[
    { name: "motd", label: "MOTD", type: "text", default: "§aMeu Servidor" },
    { name: "max", label: "max-players", type: "number", default: "20" },
    { name: "port", label: "server-port", type: "number", default: "25565" },
    { name: "mode", label: "gamemode", type: "select", options: ["survival", "creative", "adventure", "spectator"], default: "survival" },
    { name: "diff", label: "difficulty", type: "select", options: ["peaceful", "easy", "normal", "hard"], default: "normal" },
    { name: "pvp", label: "pvp", type: "select", options: ["true", "false"], default: "true" },
    { name: "view", label: "view-distance", type: "number", default: "10" },
  ]} build={(v) => `motd=${v.motd}\nmax-players=${v.max}\nserver-port=${v.port}\ngamemode=${v.mode}\ndifficulty=${v.diff}\npvp=${v.pvp}\nview-distance=${v.view}\nonline-mode=true\nspawn-protection=16`} language="properties" />;

  if (kind === "whitelist-json") return <GenericTool fields={[{ name: "list", label: "Nicks (um por linha)", type: "textarea", default: "Notch\nDream" }]} build={(v) => JSON.stringify(v.list.split("\n").filter(Boolean).map((n) => ({ uuid: "", name: n.trim() })), null, 2)} language="json" />;

  if (kind === "backup-script") return <GenericTool fields={[
    { name: "dir", label: "Pasta do mundo", type: "text", default: "/home/mc/world" },
    { name: "dest", label: "Destino", type: "text", default: "/backups" },
  ]} build={(v) => `#!/bin/bash\n# Backup gerado por C0DSXS\nDATE=$(date +%F-%H%M)\ntar -czf ${v.dest}/world-$DATE.tar.gz ${v.dir}\nfind ${v.dest} -mtime +7 -delete`} language="bash" />;

  if (kind === "mob-spawner") return <GenericTool fields={[{ name: "entity", label: "Entidade", type: "text", default: "minecraft:zombie" }, { name: "delay", label: "Delay", type: "number", default: "200" }]} build={(v) => `/setblock ~ ~ ~ minecraft:spawner{SpawnData:{entity:{id:"${v.entity}"}},MaxNearbyEntities:6,RequiredPlayerRange:16,SpawnCount:4,MaxSpawnDelay:${+v.delay*2},MinSpawnDelay:${v.delay}}`} />;

  if (kind === "loot-chest") return <GenericTool fields={[{ name: "items", label: "Itens (id x qtd por linha)", type: "textarea", default: "minecraft:diamond x 4\nminecraft:emerald x 8" }]} build={(v) => {
    const items = v.items.split("\n").filter(Boolean).map((l, i) => { const [id, q] = l.split("x").map((s) => s.trim()); return `{Slot:${i}b,id:"${id}",Count:${q || 1}b}`; }).join(",");
    return `/setblock ~ ~ ~ minecraft:chest{Items:[${items}]}`;
  }} />;

  if (kind === "structure-cmd") return <GenericTool fields={[{ name: "name", label: "Nome estrutura", type: "text", default: "codsxs:torre" }]} build={(v) => `/place structure ${v.name} ~ ~ ~`} />;
  if (kind === "worldedit-cheatsheet") return <pre className="mc-card rounded-md p-4 mono text-xs whitespace-pre-wrap">{`//wand           dar wand
//pos1 //pos2    marcar seleção
//set <bloco>    preencher
//replace a b    substituir
//copy //paste   copiar/colar
//rotate 90      rotacionar
//flip           espelhar
//undo //redo    desfazer/refazer
//sphere <b> r   esfera
//cyl <b> r h    cilindro
//brush sphere b r  pincel
//distr           estatísticas
//gmask <bloco>  máscara global`}</pre>;

  if (kind === "seed-info") return <GenericTool fields={[{ name: "s", label: "Seed", type: "text", default: "meu_seed" }]} build={(v) => { let h = 0; for (let i = 0; i < v.s.length; i++) h = Math.imul(31, h) + v.s.charCodeAt(i) | 0; return `Numérico: ${h}\nUse em level-seed do server.properties.`; }} language="text" />;

  if (kind === "slime-chunk") return <div className="space-y-2 text-sm"><p>Uma chunk é slime se o algoritmo Java do MC retornar 0 para (worldSeed, chunkX, chunkZ). Use ferramentas como Chunkbase para o cálculo exato — este site não expõe o seed do seu mundo.</p><p className="text-xs text-muted-foreground">Dica: F3+G mostra bordas de chunk. Slimes só spawnam abaixo do Y=40 em chunks válidas.</p></div>;

  if (kind === "nether-portal-calc") return <GenericTool fields={[{ name: "x", label: "X (overworld)", type: "number", default: "128" }, { name: "z", label: "Z (overworld)", type: "number", default: "128" }]} build={(v) => `Overworld: ${v.x}, ${v.z}\nNether: ${Math.round(+v.x / 8)}, ${Math.round(+v.z / 8)}\n\nConstrua o portal no Nether nessas coordenadas exatas para linkar.`} language="text" />;

  if (kind === "time-converter") return <GenericTool fields={[{ name: "t", label: "Ticks (0-24000)", type: "number", default: "6000" }]} build={(v) => { const t=+v.t; const h=Math.floor(((t/1000)+6)%24); const m=Math.floor(((t%1000)/1000)*60); return `Hora no jogo: ${String(h).padStart(2,"0")}:${String(m).padStart(2,"0")}\n0=alvorada, 6000=meio-dia, 12000=pôr do sol, 18000=meia-noite`; }} language="text" />;

  if (kind === "redstone-tick") return <GenericTool fields={[{ name: "n", label: "Redstone ticks", type: "number", default: "10" }]} build={(v) => `${v.n} redstone ticks = ${+v.n * 2} game ticks = ${(+v.n * 0.1).toFixed(1)} segundos`} language="text" />;

  if (kind === "piston-calculator") return <pre className="mc-card rounded-md p-4 mono text-xs whitespace-pre-wrap">{`Pistão normal: empurra até 12 blocos
Pistão pegajoso: puxa 1 bloco (12 com slime block chain)
Blocos que NÃO podem ser empurrados:
- Bedrock, obsidian, portais, chests, spawners, beacons.
Slime + honey NÃO se conectam.`}</pre>;

  if (kind === "hunger-table") return <pre className="mc-card rounded-md p-4 mono text-xs whitespace-pre-wrap">{`Item              Fome | Saturação
Steak / Porkchop    8  | 12.8
Golden Carrot       6  | 14.4  (melhor saturação)
Cooked Chicken      6  |  7.2
Bread               5  |  6.0
Baked Potato        5  |  6.0
Cookie              2  |  0.4
Golden Apple        4  |  9.6 + Regen II
Enchanted G. Apple  4  |  9.6 + buffs`}</pre>;

  if (kind === "villager-trades") return <GenericTool fields={[
    { name: "buy", label: "Item que pede", type: "text", default: "minecraft:emerald" }, { name: "buyN", label: "Qtd pedida", type: "number", default: "5" },
    { name: "sell", label: "Item que dá", type: "text", default: "minecraft:diamond" }, { name: "sellN", label: "Qtd dada", type: "number", default: "1" },
  ]} build={(v) => `/summon villager ~ ~ ~ {Offers:{Recipes:[{buy:{id:"${v.buy}",Count:${v.buyN}b},sell:{id:"${v.sell}",Count:${v.sellN}b},maxUses:99}]}}`} />;

  if (kind === "advancement-json") return <GenericTool fields={[
    { name: "title", label: "Título", type: "text", default: "Bem-vindo ao C0DSXS" },
    { name: "desc", label: "Descrição", type: "text", default: "Você entrou no mundo!" },
    { name: "icon", label: "Ícone (item)", type: "text", default: "minecraft:diamond" },
  ]} build={(v) => JSON.stringify({ display: { icon: { item: v.icon }, title: v.title, description: v.desc, frame: "task", show_toast: true, announce_to_chat: true }, criteria: { entered: { trigger: "minecraft:tick" } } }, null, 2)} language="json" />;

  if (kind === "recipe-json") return <GenericTool fields={[
    { name: "result", label: "Resultado", type: "text", default: "minecraft:diamond_sword" },
    { name: "count", label: "Qtd", type: "number", default: "1" },
    { name: "pattern", label: "Padrão (3 linhas 3 char)", type: "textarea", default: " D \n D \n S " },
    { name: "keys", label: "Chaves (letra=item por linha)", type: "textarea", default: "D=minecraft:diamond\nS=minecraft:stick" },
  ]} build={(v) => {
    const key: Record<string, {item: string}> = {}; v.keys.split("\n").filter(Boolean).forEach((l) => { const [k, it] = l.split("="); key[k.trim()] = { item: it.trim() }; });
    return JSON.stringify({ type: "minecraft:crafting_shaped", pattern: v.pattern.split("\n"), key, result: { item: v.result, count: +v.count } }, null, 2);
  }} language="json" />;

  if (kind === "loot-table") return <GenericTool fields={[
    { name: "item", label: "Item", type: "text", default: "minecraft:diamond" },
    { name: "min", label: "Mín", type: "number", default: "1" },
    { name: "max", label: "Máx", type: "number", default: "3" },
  ]} build={(v) => JSON.stringify({ type: "minecraft:chest", pools: [{ rolls: 1, entries: [{ type: "minecraft:item", name: v.item, functions: [{ function: "minecraft:set_count", count: { min: +v.min, max: +v.max } }] }] }] }, null, 2)} language="json" />;

  if (kind === "sound-json") return <GenericTool fields={[
    { name: "event", label: "Evento", type: "text", default: "codsxs.hello" },
    { name: "file", label: "Arquivo (sem .ogg)", type: "text", default: "codsxs/hello" },
  ]} build={(v) => JSON.stringify({ [v.event]: { sounds: [v.file] } }, null, 2)} language="json" />;

  if (kind === "model-viewer") return <GenericTool fields={[{ name: "j", label: "Model JSON", type: "textarea", default: '{"parent":"item/generated","textures":{"layer0":"item/diamond"}}' }]} build={(v) => { try { const p = JSON.parse(v.j); return `OK · parent=${p.parent || "-"}\nchaves: ${Object.keys(p).join(", ")}`; } catch { return "JSON inválido"; } }} language="text" />;

  if (kind === "banner-designer") return <GenericTool fields={[
    { name: "base", label: "Base", type: "text", default: "white_banner" },
    { name: "patterns", label: "Padrões (cor:código por linha)", type: "textarea", default: "red:cr\nblack:mc\nyellow:sku" },
  ]} build={(v) => `/give @p ${v.base}{BlockEntityTag:{Patterns:[${v.patterns.split("\n").filter(Boolean).map((l)=>{const[c,p]=l.split(":");return `{Color:${colorId(c.trim())},Pattern:"${p.trim()}"}`;}).join(",")}]}} 1`} />;

  if (kind === "shield-designer") return <GenericTool fields={[{ name: "patterns", label: "Padrões (cor:código)", type: "textarea", default: "red:cr\nwhite:sku" }]} build={(v) => `/give @p shield{BlockEntityTag:{Patterns:[${v.patterns.split("\n").filter(Boolean).map((l)=>{const[c,p]=l.split(":");return `{Color:${colorId(c.trim())},Pattern:"${p.trim()}"}`;}).join(",")}]}} 1`} />;

  if (kind === "map-art") return <div className="space-y-2 text-sm"><p>Map art precisa de processamento pesado. Recomendamos exportar sua imagem em 128×128 e usar a ferramenta local <b>MapartCraft</b>. O C0DSXS ajuda gerando a estrutura de datapack (use "Criar Datapack" nesta página).</p></div>;

  if (kind === "pixel-art") return <div className="space-y-2 text-sm"><p>Use o <b>Editor de Textura</b> para pixel-art e exporte como PNG. Para converter imagens grandes em blocos, use o gerador de datapack com uma ferramenta externa como <a className="text-primary underline" href="https://rebane2001.com/mapartcraft/" target="_blank" rel="noreferrer">MapartCraft</a>.</p></div>;

  if (kind === "cape-preview") return <div className="grid grid-cols-3 gap-3">{["MineCon2016","Migrator","Vanilla","Founder"].map((c)=>(<div key={c} className="mc-card rounded-md p-3 text-center"><div className="text-xs pixel">{c}</div><a className="text-primary text-xs underline" target="_blank" rel="noreferrer" href={`https://www.google.com/search?q=minecraft+${c}+cape`}>ver</a></div>))}</div>;

  if (kind === "skin-editor") return <TextureEditor />;

  if (kind === "armor-stand") return <GenericTool fields={[
    { name: "pose", label: "Pose", type: "select", options: ["padrao", "atacando", "acenando", "sentado"], default: "atacando" },
    { name: "name", label: "Nome", type: "text", default: "C0DSXS" },
  ]} build={(v) => {
    const poses: Record<string, string> = {
      padrao: "", atacando: "Pose:{RightArm:[-90f,0f,0f]},",
      acenando: "Pose:{RightArm:[-180f,0f,0f]},", sentado: "Pose:{LeftLeg:[-90f,0f,0f],RightLeg:[-90f,0f,0f]},",
    };
    return `/summon armor_stand ~ ~ ~ {${poses[v.pose]}CustomName:'{"text":"${v.name}"}',CustomNameVisible:1b,ShowArms:1b}`;
  }} />;

  if (kind === "dungeon-layout") {
    const roll = () => Array.from({ length: 5 }, () => Array.from({ length: 8 }, () => Math.random() < 0.6 ? "▓" : "░").join("")).join("\n");
    return <div className="space-y-2"><pre className="mc-card rounded-md p-4 mono text-xl whitespace-pre">{roll()}</pre><p className="text-xs text-muted-foreground">Clique em "Recarregar" (F5) para gerar de novo.</p></div>;
  }

  if (CMD_BUILDERS[kind]) return CMD_BUILDERS[kind]!();

  return <p className="text-sm text-muted-foreground">Ferramenta em breve. Ajude no repositório!</p>;
}

function colorId(c: string) { const m: Record<string, number> = { white:0,orange:1,magenta:2,light_blue:3,yellow:4,lime:5,pink:6,gray:7,light_gray:8,cyan:9,purple:10,blue:11,brown:12,green:13,red:14,black:15 }; return m[c] ?? 0; }
