// ============================================================
// Files page - Explorateur & Éditeur avec RBAC Discord
// Droits : Voir (filesView), Modifier existant (filesEdit), Push (filesPush)
// ============================================================

const { useState: _useState, useMemo: _useMemo, useEffect: _useEffect, useRef: _useRef } = React;

function buildTree(filesystem, folders) {
  const paths = Object.keys(filesystem);
  const allFolders = new Set();

  for (const p of paths) {
    const parts = p.split("/").filter(Boolean);
    let cur = "";
    for (let i = 0; i < parts.length - 1; i++) {
      cur += "/" + parts[i];
      allFolders.add(cur);
    }
  }

  for (const fp of Object.keys(folders || {})) {
    const parts = fp.split("/").filter(Boolean);
    let cur = "";
    for (let i = 0; i < parts.length; i++) {
      cur += "/" + parts[i];
      allFolders.add(cur);
    }
  }

  const tree = {};
  for (const f of allFolders) tree[f] = { folders: [], files: [] };
  tree["/"] = { folders: [], files: [] };

  for (const f of allFolders) {
    const parent = f.split("/").slice(0, -1).join("/") || "/";
    if (!tree[parent]) tree[parent] = { folders: [], files: [] };
    tree[parent].folders.push(f);
  }

  for (const p of paths) {
    const parent = p.split("/").slice(0, -1).join("/") || "/";
    if (!tree[parent]) tree[parent] = { folders: [], files: [] };
    tree[parent].files.push(p);
  }

  return tree;
}
window.buildTree = buildTree;

function fmtBytes(b) {
  if (b < 1024) return b + " B";
  if (b < 1024 * 1024) return (b / 1024).toFixed(1) + " KB";
  if (b < 1024 * 1024 * 1024) return (b / 1024 / 1024).toFixed(1) + " MB";
  return (b / 1024 / 1024 / 1024).toFixed(2) + " GB";
}

function UploadProgress({ upload, onCancel }) {
  const { total, done, totalBytes, doneBytes, currentName } = upload;
  const pct = totalBytes > 0 ? Math.min(100, (doneBytes / totalBytes) * 100) : 0;

  return (
    <div className="upload-card">
      <div className="upload-h">
        <div style={{ display: "flex", alignItems: "center", gap: 10, flex: 1, minWidth: 0 }}>
          <div className="spinner" style={{ width: 16, height: 16, borderWidth: 2 }}></div>
          <strong>Téléversement / Push en cours</strong>
          <span style={{ color: "var(--muted)", fontSize: 12 }}>{done} / {total} fichier{total > 1 ? "s" : ""}</span>
        </div>
        <div className="upload-actions">
          <button className="btn btn-sm btn-danger" onClick={onCancel} title="Annuler">
            <Icon name="x" /> Annuler
          </button>
          <div className="pct" style={{ color: "var(--accent)" }}>{pct.toFixed(0)}%</div>
        </div>
      </div>
      <div className="upload-bar"><div className="upload-bar-fill" style={{ width: pct + "%" }}></div></div>
      <div className="upload-meta">
        <div className="cur mono" title={currentName}>{currentName || "-"}</div>
        <div className="info">
          <span>{fmtBytes(doneBytes)} / {fmtBytes(totalBytes)}</span>
        </div>
      </div>
    </div>
  );
}

function ConfigUnderConstruction({ user, perms }) {
  return (
    <div
      className="card"
      style={{
        padding: "40px 28px",
        textAlign: "center",
        maxWidth: 640,
        margin: "24px auto",
      }}
    >
      {/* Main Icon - Sobre, sans effet néon */}
      <div
        style={{
          width: 58,
          height: 58,
          borderRadius: 12,
          background: "var(--surface-2)",
          border: "1px solid var(--border)",
          display: "grid",
          placeItems: "center",
          margin: "0 auto 16px",
          color: "var(--text-dim)",
        }}
      >
        <Icon name="folderOpen" size={26} />
      </div>

      {/* Status Pill - Sobre, sans néon */}
      <div style={{ marginBottom: 14 }}>
        <span
          style={{
            display: "inline-flex",
            alignItems: "center",
            gap: 7,
            padding: "4px 12px",
            borderRadius: 6,
            background: "var(--surface-2)",
            border: "1px solid var(--border)",
            color: "var(--warn)",
            fontSize: 12,
            fontWeight: 500,
          }}
        >
          <span
            style={{
              width: 6,
              height: 6,
              borderRadius: "50%",
              background: "var(--warn)",
              display: "inline-block",
            }}
          />
          <span>Module en cours de développement</span>
        </span>
      </div>

      <h2 style={{ fontSize: 20, fontWeight: 700, margin: "0 0 8px", color: "var(--text)" }}>
        Page de configuration indisponible
      </h2>

      <p style={{ color: "var(--text-dim)", fontSize: 13, lineHeight: 1.6, margin: "0 auto 22px", maxWidth: 500 }}>
        Cette section n'est pas encore disponible. L'explorateur de fichiers et l'éditeur de configuration et scripts du serveur FiveM sont actuellement en cours de développement et seront activés lors d'une prochaine mise à jour.
      </p>

      {/* Permission verification box - Sobre et standard */}
      <div
        style={{
          background: "var(--bg-2)",
          border: "1px solid var(--border)",
          borderRadius: 8,
          padding: "14px 18px",
          textAlign: "left",
          maxWidth: 460,
          margin: "0 auto",
        }}
      >
        <div
          style={{
            fontSize: 11,
            fontWeight: 600,
            textTransform: "uppercase",
            letterSpacing: "0.06em",
            color: "var(--muted)",
            marginBottom: 10,
            display: "flex",
            alignItems: "center",
            gap: 6,
          }}
        >
          <Icon name="check" size={13} style={{ color: "var(--ok)" }} />
          <span>Statut de vos permissions RBAC</span>
        </div>
        <div style={{ display: "flex", flexDirection: "column", gap: 8, fontSize: 12 }}>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
            <span style={{ color: "var(--text-dim)" }}>Consultation des fichiers (filesView) :</span>
            <span style={{ color: "var(--ok)", fontWeight: 600 }}>Autorisé</span>
          </div>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
            <span style={{ color: "var(--text-dim)" }}>Édition de scripts (filesEdit) :</span>
            <span style={{ color: perms?.filesEdit ? "var(--ok)" : "var(--muted)", fontWeight: perms?.filesEdit ? 600 : 400 }}>
              {perms?.filesEdit ? "Autorisé" : "Non attribué"}
            </span>
          </div>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
            <span style={{ color: "var(--text-dim)" }}>Téléversement / Push (filesPush) :</span>
            <span style={{ color: perms?.filesPush ? "var(--ok)" : "var(--muted)", fontWeight: perms?.filesPush ? 600 : 400 }}>
              {perms?.filesPush ? "Autorisé" : "Non attribué"}
            </span>
          </div>
        </div>
      </div>
    </div>
  );
}

function FilesPage({ user, perms }) {
  // Module temporairement indisponible (en cours de développement)
  // L'accès au mode aperçu est désactivé par sécurité.
  // L'intégralité du code et de l'éditeur existant ci-dessous est conservée pour réactivation future.
  return <ConfigUnderConstruction user={user} perms={perms} />;

  // === CODE D'ORIGINE CONSERVÉ POUR DÉVELOPPEMENTS ULTÉRIEURS ===
  const [fs, setFs] = _useState({});
  const [folders, setFolders] = _useState({});
  const [loading, setLoading] = _useState(true);
  const [selected, setSelected] = _useState(null);
  const [expanded, setExpanded] = _useState(() => new Set(["/server", "/scripts", "/scripts/economy", "/assets"]));
  const [draft, setDraft] = _useState({});
  const [fileContents, setFileContents] = _useState({});
  const [toast, setToast] = _useState(null);
  const [renaming, setRenaming] = _useState(null);
  const [renameVal, setRenameVal] = _useState("");
  const [confirmDel, setConfirmDel] = _useState(null);
  const [dragOver, setDragOver] = _useState(false);
  const [upload, setUpload] = _useState(null);

  const canEdit = perms.filesEdit || false;
  const canPush = perms.filesPush || false;

  const showToast = (msg, kind = "ok") => {
    setToast({ msg, kind });
    setTimeout(() => setToast(null), 2800);
  };

  // Charger le filesystem depuis le backend
  const loadFilesystem = async () => {
    try {
      const resp = await fetch("/api/files");
      if (!resp.ok) throw new Error("Accès refusé au système de fichiers.");
      const data = await resp.json();
      setFs(data.filesystem || {});
      setFolders(data.folders || {});
      setLoading(false);
      // Sélectionner le 1er fichier si rien n'est sélectionné
      if (!selected) {
        const first = Object.keys(data.filesystem || {})[0];
        if (first) setSelected(first);
      }
    } catch (err) {
      showToast(err.message, "err");
      setLoading(false);
    }
  };

  _useEffect(() => {
    if (previewMode) {
      loadFilesystem();
    }
  }, [previewMode]);

  // Charger le contenu du fichier sélectionné
  _useEffect(() => {
    if (!selected || !fs[selected] || fs[selected].type !== "file") return;
    if (fileContents[selected] !== undefined) return;

    fetch(`/api/files/content?path=${encodeURIComponent(selected)}`)
      .then((r) => r.json())
      .then((res) => {
        if (res.content !== undefined) {
          setFileContents((c) => ({ ...c, [selected]: res.content }));
        }
      })
      .catch((e) => console.error("Error loading file content", e));
  }, [selected, fs]);

  const tree = _useMemo(() => buildTree(fs, folders), [fs, folders]);
  const isFolder = selected && tree[selected];
  const selectedEntry = selected ? fs[selected] : null;

  const folderCfg = (path) => folders[path] || {};

  // Enregistrer les modifications d'un fichier existant (Nécessite ROLE_FILES_EDIT)
  const handleSave = async () => {
    if (!canEdit) {
      showToast("Votre grade Discord ne permet pas de modifier les fichiers existants.", "err");
      return;
    }
    const currentContent = draft[selected] !== undefined ? draft[selected] : fileContents[selected];
    if (currentContent === undefined) return;

    try {
      const resp = await fetch("/api/files/save", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ path: selected, content: currentContent }),
      });
      const data = await resp.json();
      if (resp.ok) {
        setFileContents((c) => ({ ...c, [selected]: currentContent }));
        const next = { ...draft };
        delete next[selected];
        setDraft(next);
        showToast("Fichier sauvegardé avec succès sur le serveur !", "ok");
      } else {
        showToast(data.error || "Erreur lors de la sauvegarde", "err");
      }
    } catch (e) {
      showToast("Erreur de connexion au serveur", "err");
    }
  };

  // Uploader / Push des fichiers (Nécessite ROLE_FILES_PUSH)
  const runUpload = async (fileList, baseFolder) => {
    if (!canPush) {
      showToast("Votre grade Discord ne permet pas d'ajouter/push des fichiers (ROLE_FILES_PUSH requis).", "err");
      return;
    }

    const files = Array.from(fileList);
    if (files.length === 0) return;

    const totalBytes = files.reduce((s, f) => s + f.size, 0);
    setUpload({
      active: true,
      total: files.length,
      done: 0,
      totalBytes,
      doneBytes: 0,
      currentName: files[0].name,
    });

    let successCount = 0;
    for (const file of files) {
      const relPath = file.webkitRelativePath || file.name;
      const targetPath = (baseFolder + "/" + relPath).replace(/\/+/g, "/");

      setUpload((u) => u && { ...u, currentName: relPath });

      try {
        const textContent = await file.text();
        const ext = targetPath.split(".").pop().toLowerCase();
        const langMap = { lua: "lua", json: "json", cfg: "ini", ini: "ini", js: "javascript" };

        const resp = await fetch("/api/files/upload", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            path: targetPath,
            content: textContent,
            mime: file.type || "text/plain",
            language: langMap[ext] || "text",
          }),
        });

        if (resp.ok) successCount++;
      } catch (err) {
        console.error("Upload error", err);
      }

      setUpload((u) => u && { ...u, done: u.done + 1, doneBytes: u.doneBytes + file.size });
    }

    setUpload(null);
    await loadFilesystem();
    showToast(`${successCount}/${files.length} fichier(s) pushé(s) avec succès !`, "ok");
  };

  // Renommer (Nécessite ROLE_FILES_EDIT)
  const handleRename = async (oldPath) => {
    if (!canEdit) {
      showToast("Votre grade ne permet pas de renommer des fichiers.", "err");
      return;
    }
    if (!renameVal || renameVal.includes("/")) {
      showToast("Nom de fichier invalide", "err");
      return;
    }
    const parent = oldPath.split("/").slice(0, -1).join("/") || "/";
    const newPath = `${parent === "/" ? "" : parent}/${renameVal}`.replace(/\/+/g, "/");

    try {
      const resp = await fetch("/api/files/rename", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ oldPath, newPath }),
      });
      const data = await resp.json();
      if (resp.ok) {
        await loadFilesystem();
        setSelected(newPath);
        setRenaming(null);
        showToast("Renommé avec succès", "ok");
      } else {
        showToast(data.error || "Erreur de renommage", "err");
      }
    } catch (e) {
      showToast("Erreur de connexion", "err");
    }
  };

  // Supprimer (Nécessite ROLE_FILES_PUSH)
  const handleDelete = async (targetPath) => {
    if (!canPush) {
      showToast("Votre grade ne permet pas de supprimer des éléments (ROLE_FILES_PUSH requis).", "err");
      return;
    }

    try {
      const resp = await fetch("/api/files/delete", {
        method: "DELETE",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ path: targetPath }),
      });
      const data = await resp.json();
      if (resp.ok) {
        await loadFilesystem();
        setConfirmDel(null);
        const parent = targetPath.split("/").slice(0, -1).join("/") || "/";
        setSelected(parent === "/" ? null : parent);
        showToast("Élément supprimé", "ok");
      } else {
        showToast(data.error || "Erreur de suppression", "err");
      }
    } catch (e) {
      showToast("Erreur de communication avec le serveur", "err");
    }
  };

  // Node composant d'arborescence
  const TreeFolder = ({ path }) => {
    const node = tree[path];
    if (!node) return null;
    const name = path.split("/").pop() || "/";
    const isOpen = expanded.has(path);
    const sel = selected === path;

    return (
      <div>
        <div
          className={`tree-node ${sel ? "sel" : ""}`}
          onClick={() => {
            setSelected(path);
            const n = new Set(expanded);
            n.has(path) ? n.delete(path) : n.add(path);
            setExpanded(n);
          }}
        >
          <span className="tw">{isOpen ? <Icon name="chevD" size={10} /> : <Icon name="chevR" size={10} />}</span>
          <Icon name={isOpen ? "folderOpen" : "folder"} />
          <span>{name}</span>
        </div>
        {isOpen && (
          <div className="tree-children">
            {node.folders.map((f) => <TreeFolder key={f} path={f} />)}
            {node.files.map((f) => {
              const e = fs[f] || {};
              const fn = f.split("/").pop();
              const isImg = e.mime && e.mime.startsWith("image/");
              return (
                <div key={f} className={`tree-node ${selected === f ? "sel" : ""}`} onClick={() => setSelected(f)}>
                  <span className="tw"></span>
                  <Icon name={isImg ? "image" : (e.language === "lua" || e.language === "javascript") ? "code" : "file"} />
                  <span>{fn}</span>
                </div>
              );
            })}
          </div>
        )}
      </div>
    );
  };

  const breadcrumb = (path) => {
    const parts = (path || "").split("/").filter(Boolean);
    return (
      <>
        <span className="seg">/</span>
        {parts.map((p, i) => (
          <React.Fragment key={i}>
            {i > 0 && <span className="sep">/</span>}
            <span className="seg">{p}</span>
          </React.Fragment>
        ))}
      </>
    );
  };

  const roots = tree["/"]?.folders || [];

  if (!previewMode) {
    return (
      <ConfigUnderConstruction
        user={user}
        perms={perms}
        onOpenPreview={() => {
          setPreviewMode(true);
          loadFilesystem();
        }}
      />
    );
  }

  if (loading) {
    return (
      <div style={{ textAlign: "center", padding: 50 }}>
        <div className="spinner" style={{ width: 26, height: 26, margin: "0 auto 10px" }}></div>
        <div style={{ color: "var(--text-dim)" }}>Chargement de l'arborescence serveur…</div>
      </div>
    );
  }

  return (
    <div className="files-grid">
      <div className="tree">
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "4px 8px 8px" }}>
          <div style={{ fontSize: 10, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--muted)", fontWeight: 500 }}>
            Arborescence
          </div>
          <div style={{ display: "flex", gap: 4 }}>
            {canPush && <span className="dev-pill" style={{ fontSize: 8, padding: "2px 5px" }}>Push Actif</span>}
            {canEdit && <span className="dev-pill" style={{ fontSize: 8, padding: "2px 5px", color: "var(--info)", borderColor: "var(--info)" }}>Édition</span>}
          </div>
        </div>

        {roots.length === 0 && <div className="empty" style={{ padding: 20, fontSize: 12 }}>Aucun dossier accessible.</div>}
        {roots.map((r) => <TreeFolder key={r} path={r} />)}
      </div>

      <div className="file-pane">
        {!selected ? (
          <div className="empty">Sélectionnez un fichier ou dossier dans l'arborescence.</div>
        ) : isFolder ? (
          <>
            <div className="file-pane-h">
              <div className="path">{breadcrumb(selected)}</div>
              {folderCfg(selected).label && (
                <span className="role-pill" style={{ background: "var(--surface-3)", color: "var(--text-dim)", border: "1px solid var(--border)" }}>
                  {folderCfg(selected).label}
                </span>
              )}
              {canEdit && (
                <button className="btn btn-sm" onClick={() => { setRenaming(selected); setRenameVal(selected.split("/").pop()); }}>
                  <Icon name="pencil" /> Renommer
                </button>
              )}
              {canPush && (
                <button className="btn btn-sm btn-danger" onClick={() => setConfirmDel(selected)}>
                  <Icon name="trash" /> Supprimer
                </button>
              )}
            </div>

            {canPush ? (
              <div
                className={`dropzone ${dragOver ? "hot" : ""}`}
                onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
                onDragLeave={() => setDragOver(false)}
                onDrop={(e) => {
                  e.preventDefault();
                  setDragOver(false);
                  if (e.dataTransfer.files) runUpload(e.dataTransfer.files, selected);
                }}
              >
                <Icon name="upload" />
                <div style={{ flex: 1 }}>
                  <div>Glissez-déposez des fichiers pour les <strong>pusher sur le serveur</strong></div>
                  <div style={{ fontSize: 11, color: "var(--muted)", marginTop: 2 }}>
                    Dossier de destination : <strong className="mono">{selected}</strong>
                  </div>
                </div>
                <label className="btn btn-sm btn-primary" style={{ cursor: "pointer" }}>
                  <Icon name="plus" /> Ajouter des fichiers
                  <input
                    type="file"
                    multiple
                    style={{ display: "none" }}
                    onChange={(e) => { runUpload(e.target.files, selected); e.target.value = ""; }}
                  />
                </label>
              </div>
            ) : (
              <div style={{ padding: "10px 14px", background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 8, fontSize: 12, color: "var(--muted)", display: "flex", alignItems: "center", gap: 8, marginBottom: 12 }}>
                <Icon name="lock" /> Votre grade Discord ne permet pas de pusher ou d'ajouter de nouveaux fichiers (ROLE_FILES_PUSH requis).
              </div>
            )}

            {upload && upload.active && (
              <UploadProgress upload={upload} onCancel={() => setUpload(null)} />
            )}

            <div className="file-pane-body">
              <div className="file-listing">
                <div className="h">Nom</div>
                <div className="h">Taille</div>
                <div className="h">Type</div>
                <div className="h">Statut</div>
                <div className="h" style={{ justifyContent: "flex-end" }}>Actions</div>

                {(tree[selected]?.folders || []).map((f) => (
                  <div className="file-row dir" key={f} onClick={() => setSelected(f)}>
                    <div className="c name">
                      <Icon name="folder" />
                      <span>{f.split("/").pop()}</span>
                    </div>
                    <div className="c size">-</div>
                    <div className="c type">Dossier</div>
                    <div className="c mod">Système</div>
                    <div className="c acts" onClick={(e) => e.stopPropagation()}>
                      {canPush && (
                        <button className="icon-btn danger" title="Supprimer" onClick={() => setConfirmDel(f)}>
                          <Icon name="trash" />
                        </button>
                      )}
                    </div>
                  </div>
                ))}

                {(tree[selected]?.files || []).map((f) => {
                  const e = fs[f] || {};
                  const fn = f.split("/").pop();
                  return (
                    <div className="file-row" key={f} onClick={() => setSelected(f)}>
                      <div className="c name">
                        <Icon name="code" />
                        <span>{fn}</span>
                      </div>
                      <div className="c size">{fmtBytes(e.size || 0)}</div>
                      <div className="c type">{e.language || "Texte"}</div>
                      <div className="c mod">{canEdit ? "Modifiable" : "Lecture"}</div>
                      <div className="c acts" onClick={(ev) => ev.stopPropagation()}>
                        <button className="icon-btn" title="Ouvrir" onClick={() => setSelected(f)}>
                          <Icon name="edit" />
                        </button>
                        {canPush && (
                          <button className="icon-btn danger" title="Supprimer" onClick={() => setConfirmDel(f)}>
                            <Icon name="trash" />
                          </button>
                        )}
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          </>
        ) : (
          /* File Editor / Viewer */
          (() => {
            const e = selectedEntry || {};
            const content = draft[selected] !== undefined ? draft[selected] : (fileContents[selected] || "");
            const dirty = draft[selected] !== undefined && draft[selected] !== fileContents[selected];

            return (
              <>
                <div className="file-pane-h">
                  <div className="path">{breadcrumb(selected)}</div>
                  <span className="role-pill" style={{ background: "var(--surface-3)", color: "var(--text-dim)", border: "1px solid var(--border)" }}>
                    {e.language || "text"}
                  </span>
                  {dirty && <span className="dirty" style={{ fontSize: 11 }}>● Modifié non sauvegardé</span>}

                  {canEdit ? (
                    <button className="btn btn-sm btn-primary" disabled={!dirty} onClick={handleSave}>
                      <Icon name="save" /> Enregistrer les modifications
                    </button>
                  ) : (
                    <span className="role-pill" style={{ background: "transparent", color: "var(--muted)", border: "1px solid var(--border)" }}>
                      <Icon name="lock" size={11} style={{ marginRight: 4 }} /> Lecture seule
                    </span>
                  )}

                  {canEdit && (
                    <button className="btn btn-sm" onClick={() => { setRenaming(selected); setRenameVal(selected.split("/").pop()); }}>
                      <Icon name="pencil" />
                    </button>
                  )}
                  {canPush && (
                    <button className="btn btn-sm btn-danger" onClick={() => setConfirmDel(selected)}>
                      <Icon name="trash" />
                    </button>
                  )}
                </div>

                {!canEdit && (
                  <div className="editor-readonly-banner">
                    <Icon name="lock" />
                    Mode lecture seule - votre grade Discord ne permet pas de modifier ce fichier existant (ROLE_FILES_EDIT requis).
                  </div>
                )}

                <CodeEditor
                  value={content}
                  language={e.language || "text"}
                  readOnly={!canEdit}
                  onChange={(v) => setDraft({ ...draft, [selected]: v })}
                />
              </>
            );
          })()
        )}
      </div>

      {renaming && (
        <div className="modal-bg" onClick={() => setRenaming(null)}>
          <div className="modal" onClick={(e) => e.stopPropagation()}>
            <h3>Renommer l'élément</h3>
            <p>Saisissez le nouveau nom :</p>
            <input
              className="input"
              autoFocus
              value={renameVal}
              onChange={(e) => setRenameVal(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === "Enter") handleRename(renaming);
                if (e.key === "Escape") setRenaming(null);
              }}
            />
            <div className="modal-acts" style={{ marginTop: 14 }}>
              <button className="btn" onClick={() => setRenaming(null)}>Annuler</button>
              <button className="btn btn-primary" onClick={() => handleRename(renaming)}>Renommer</button>
            </div>
          </div>
        </div>
      )}

      {confirmDel && (
        <div className="modal-bg" onClick={() => setConfirmDel(null)}>
          <div className="modal" onClick={(e) => e.stopPropagation()}>
            <h3>Supprimer l'élément ?</h3>
            <p>Cette action est irréversible. L'élément <strong className="mono">{confirmDel}</strong> sera supprimé.</p>
            <div className="modal-acts">
              <button className="btn" onClick={() => setConfirmDel(null)}>Annuler</button>
              <button className="btn btn-danger" onClick={() => handleDelete(confirmDel)}>Confirmer la suppression</button>
            </div>
          </div>
        </div>
      )}

      {toast && (
        <div className={`toast ${toast.kind}`}>
          <span className="toast-ico"><Icon name={toast.kind === "ok" ? "check" : "warn"} size={14} /></span>
          {toast.msg}
        </div>
      )}
    </div>
  );
}

window.FilesPage = FilesPage;
