// Modals: Upload + Create Folder
const { Button: BtnC, Info: InfoC, Modal: ModalC, FileIcon: FIC, Ic: IcC } = window.UI;
const { useState: uSC, useEffect: uEC, useRef: uRC, useMemo: uMC } = React;

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const RETRY_DELAYS = [3000, 5000, 8000]; // ~16s, "breve"
const isScanUnavailable = (err) =>
  !!(err && err.body && Array.isArray(err.body.rejected) &&
     err.body.rejected.some((r) => r.reason === "scan_unavailable"));

function useUploadState(onUploaded) {
  const [files, setFiles]       = uSC([]);
  const [sending, setSending]   = uSC(false);
  const [phase, setPhase]       = uSC("idle");
  const [speeds, setSpeeds]     = uSC([]);
  const [folderId, setFolderId] = uSC("");
  const [note, setNote]         = uSC("");
  const [folders, setFolders]   = uSC([]);
  const [toastShow, setToastShow] = uSC(false);
  const [toastDone, setToastDone] = uSC(false);
  const speedRef = uRC({});
  const inputRef = uRC(null);

  const fmt = (b) => b > 1e9 ? (b / 1e9).toFixed(1) + " GB" : b > 1e6 ? (b / 1e6).toFixed(0) + " MB" : Math.max(1, Math.round(b / 1e3)) + " KB";
  const fmtSpeed = (bps) => bps > 1e6 ? (bps / 1e6).toFixed(1) + " MB/s" : bps > 1e3 ? Math.round(bps / 1e3) + " KB/s" : Math.round(bps) + " B/s";

  const initForNew = (dfid) => {
    setFiles([]); setNote(""); setSending(false); setPhase("idle"); setSpeeds([]);
    speedRef.current = {};
    setFolderId(dfid || "");
    setToastShow(false); setToastDone(false);
    window.API_CLIENT.apiGet("/folders")
      .then(async (data) => {
        let list = (data || []).filter(f => f.status !== "archived" && f.status !== "deleted");
        if (dfid && !list.find(f => f.id === dfid)) {
          try {
            const current = await window.API_CLIENT.apiGet("/folders/" + dfid);
            if (current) list = [current, ...list];
          } catch {}
        }
        setFolders(list);
        if (!dfid && list.length > 0) setFolderId(list[0].id);
      })
      .catch(() => {});
  };

  const addFiles = (fl) => {
    const adds = Array.from(fl).map((f) => ({
      file: f, name: f.name, size: f.size,
      ext: f.name.split(".").pop().toLowerCase() || "",
      progress: 0, done: false, error: "", retrying: false, retryAttempt: 0,
    }));
    setFiles((curr) => [...curr, ...adds]);
  };

  const handleSend = async () => {
    if (!folderId || files.length === 0) return;
    setSending(true); setPhase("uploading");
    setSpeeds(files.map(() => 0));
    setToastShow(true); setToastDone(false);
    speedRef.current = {};
    let hasError = false;

    for (let i = 0; i < files.length; i++) {
      const entry = files[i];
      if (entry.done || entry.error) continue;
      speedRef.current[i] = { lastTime: Date.now(), lastLoaded: 0 };

      const onProgress = (pct, loaded) => {
        const now = Date.now();
        const ref = speedRef.current[i] || { lastTime: now, lastLoaded: 0 };
        const elapsed = (now - ref.lastTime) / 1000;
        if (elapsed >= 0.3) {
          const speed = (loaded - ref.lastLoaded) / elapsed;
          speedRef.current[i] = { lastTime: now, lastLoaded: loaded };
          setSpeeds((curr) => curr.map((s, idx) => idx === i ? speed : s));
        }
        setFiles((curr) => curr.map((f, idx) => idx === i ? { ...f, progress: pct } : f));
      };

      let attempt = 0;
      while (true) {
        const fd = new FormData();
        fd.append("files", entry.file, entry.name);
        if (note) fd.append("note", note);
        try {
          await window.API_CLIENT.apiUpload("/folders/" + folderId + "/files", fd, onProgress);
          setFiles((curr) => curr.map((f, idx) => idx === i ? { ...f, progress: 100, done: true, retrying: false } : f));
          if (onUploaded) onUploaded();
          break;
        } catch (err) {
          if (isScanUnavailable(err) && attempt < RETRY_DELAYS.length) {
            const wait = RETRY_DELAYS[attempt];
            attempt++;
            speedRef.current[i] = { lastTime: Date.now(), lastLoaded: 0 };
            setFiles((curr) => curr.map((f, idx) => idx === i ? { ...f, retrying: true, retryAttempt: attempt, progress: 0, error: "" } : f));
            await sleep(wait);
            continue;
          }
          hasError = true;
          setFiles((curr) => curr.map((f, idx) => idx === i ? { ...f, error: err.message || "Errore", retrying: false } : f));
          break;
        }
      }
    }

    setSending(false);
    if (!hasError) {
      setPhase("done"); setToastDone(true);
      setTimeout(() => { setToastShow(false); }, 4000);
    } else {
      setPhase("error"); setToastDone(false);
    }
  };

  const dismiss = () => {
    setToastShow(false); setToastDone(false);
    setFiles([]); setPhase("idle"); setSending(false); setSpeeds([]);
    speedRef.current = {};
  };

  const computed = uMC(() => {
    const allDone = files.length > 0 && files.every((f) => f.done || f.error);
    const doneCount = files.filter((f) => f.done).length;
    const hasError = files.some((f) => f.error);
    let activeFile = null;
    for (let i = 0; i < files.length; i++) {
      if (!files[i].done && !files[i].error) { activeFile = files[i]; break; }
    }
    return { allDone, doneCount, hasError, activeFile };
  }, [files]);

  return {
    files, setFiles, sending, phase, speeds, folderId, setFolderId, note, setNote,
    folders, setFolders,
    toastShow, toastDone, setToastShow,
    speedRef, inputRef,
    initForNew, addFiles, handleSend, dismiss,
    fmt, fmtSpeed,
    ...computed,
  };
}
window.useUploadState = useUploadState;

function UploadModal({ t, lang, open, onClose, defaultFolderId, upload }) {
  const {
    files, setFiles, sending, phase, speeds,
    folderId, setFolderId, note, setNote,
    folders,
    speedRef, inputRef,
    initForNew, addFiles, handleSend,
    fmt, fmtSpeed,
    allDone, doneCount, hasError, activeFile,
    toastShow,
  } = upload;

  uEC(() => {
    if (!open) return;
    if (phase === "uploading") return;
    initForNew(defaultFolderId);
  }, [open]);

  const active = phase === "uploading" || phase === "done" || phase === "error";
  const [drag, setDrag] = uSC(false);

  if (active) {
    return (
      <ModalC open={open} onClose={onClose}
        title={allDone
          ? (lang === "it" ? "Caricamento completato" : "Upload complete")
          : hasError
            ? (lang === "it" ? "Caricamento completato con errori" : "Upload completed with errors")
            : (lang === "it" ? "Caricamento in corso…" : "Uploading…")}
        sub={lang === "it" ? `${doneCount} di ${files.length} file` : `${doneCount} of ${files.length} files`}
        width={520}
        footer={allDone && (
          <div style={{ fontSize: 13, color: "var(--ink-soft)", display: "flex", alignItems: "center", gap: 6 }}>
            <IcC.check style={{ color: "#1F7A4D" }} />
            {lang === "it" ? "La cartella si sta aggiornando…" : "Folder is updating…"}
          </div>
        )}>
        <div className="col" style={{ gap: 10 }}>
          {files.map((f, i) => (
            <div className="upload-item" key={i} style={{ alignItems: "center" }}>
              <FIC ext={f.ext} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: "flex", justifyContent: "space-between", gap: 8 }}>
                  <span style={{ fontSize: 13, fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{f.name}</span>
                  <span style={{ fontSize: 12, color: "var(--ink-soft)", whiteSpace: "nowrap", flexShrink: 0 }}>
                    {f.done ? fmt(f.size) : f.error ? "" : speeds[i] > 0 ? fmtSpeed(speeds[i]) : fmt(f.size)}
                  </span>
                </div>
                {!f.done && !f.error && (
                  <div className="progress" style={{ marginTop: 6 }}>
                    <span style={{ width: f.progress + "%" }} />
                  </div>
                )}
                {f.retrying && (
                  <div style={{ fontSize: 12, color: "var(--ink-soft)", marginTop: 4 }}>
                    {t.upload.scan_retry} ({f.retryAttempt}/{RETRY_DELAYS.length})
                  </div>
                )}
                {f.done && <span className="badge" data-tone="ok" style={{ marginTop: 4 }}><IcC.check /> {t.folder.status.uploaded}</span>}
                {f.error && <div style={{ fontSize: 12, color: "#B23A3A", marginTop: 4 }}>{f.error}</div>}
              </div>
            </div>
          ))}
        </div>
      </ModalC>
    );
  }

  return (
    <ModalC open={open} onClose={onClose} title={t.upload.title} sub={t.upload.sub} width={600}
      footer={
        <>
          <div style={{ marginRight: "auto", fontSize: 12, color: "var(--ink-soft)", display: "flex", alignItems: "center", gap: 6 }}>
            <IcC.info /> {t.upload.tip_resume}
          </div>
          <BtnC variant="ghost" onClick={onClose}>{t.upload.cancel}</BtnC>
          <BtnC variant="primary" icon={<IcC.upload />} disabled={files.length === 0}
            onClick={handleSend}>
            {t.upload.send}
          </BtnC>
        </>
      }>
      <div className="col" style={{ gap: 16 }}>
        <div className="field">
          <div className="field-row">
            <label className="label">{t.upload.to_folder}</label>
            <InfoC>{lang === "it" ? "Puoi cambiare destinazione anche dopo." : "You can change destination later."}</InfoC>
          </div>
          <select className="input" value={folderId} onChange={(e) => setFolderId(e.target.value)}>
            {folders.map((f) => (
              <option key={f.id} value={f.id}>{f.name}</option>
            ))}
            {folders.length === 0 && <option value="">{lang === "it" ? "Nessuna cartella" : "No folders"}</option>}
          </select>
        </div>

        <div className="dropzone" data-drag={drag}
          onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
          onDragLeave={() => setDrag(false)}
          onDrop={(e) => { e.preventDefault(); setDrag(false); addFiles(e.dataTransfer.files); }}
          onClick={() => inputRef.current?.click()}>
          <IcC.cloud />
          <div>
            <div className="big">{t.upload.drop_a}</div>
            <div style={{ color: "var(--ink-soft)", marginTop: 2 }}>{t.upload.drop_b}</div>
          </div>
          <div className="hint">{t.upload.drop_hint}</div>
          <input ref={inputRef} type="file" multiple style={{ display: "none" }}
            onChange={(e) => addFiles(e.target.files)} />
        </div>

        {files.length > 0 && (
          <div>
            <div style={{ fontSize: 12.5, color: "var(--ink-soft)", marginBottom: 6 }}>
              {files.length} {lang === "it" ? "file selezionati" : "files selected"}
            </div>
            <div>
              {files.map((f, i) => (
                <div className="upload-item" key={i}>
                  <FIC ext={f.ext} />
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ display: "flex", justifyContent: "space-between", gap: 8 }}>
                      <span style={{ fontSize: 13, fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{f.name}</span>
                      <span style={{ fontSize: 12, color: "var(--ink-soft)" }}>{fmt(f.size)}</span>
                    </div>
                  </div>
                  <button className="iconbtn" onClick={() => setFiles((c) => c.filter((_, idx) => idx !== i))}><IcC.x /></button>
                </div>
              ))}
            </div>
          </div>
        )}

        <div className="field">
          <div className="field-row">
            <label className="label">{t.upload.add_note}</label>
            <InfoC>{lang === "it" ? "Una nota qui resta legata a questo gruppo di file." : "A note here stays linked to this upload batch."}</InfoC>
          </div>
          <textarea className="input" placeholder={t.upload.note_ph} value={note} onChange={(e) => setNote(e.target.value)} />
        </div>
      </div>
    </ModalC>
  );
}

function CreateFolderModal({ t, lang, open, onClose, onCreated, defaultParentId }) {
  const [name, setName]     = uSC("");
  const [note, setNote]     = uSC("");
  const [parent, setParent] = uSC("");
  const [folders, setFolders] = uSC([]);
  const [saving, setSaving] = uSC(false);
  const [error, setError]   = uSC("");

  uEC(() => {
    if (!open) return;
    setName(""); setNote(""); setParent(defaultParentId || ""); setError(""); setSaving(false);
    window.API_CLIENT.apiGet("/folders")
      .then(async (data) => {
        let list = (data || []).filter(f => f.status !== "archived" && f.status !== "deleted");
        if (defaultParentId && !list.find(f => f.id === defaultParentId)) {
          try {
            const current = await window.API_CLIENT.apiGet("/folders/" + defaultParentId);
            if (current) list = [current, ...list];
          } catch {}
        }
        setFolders(list);
      })
      .catch(() => {});
  }, [open]);

  const handleCreate = async () => {
    if (!name.trim()) return;
    setSaving(true); setError("");
    try {
      await window.API_CLIENT.apiPost("/folders", {
        name: name.trim(),
        note: note || "",
        parent_id: parent || null,
      });
      if (onCreated) onCreated();
      onClose();
    } catch (err) {
      setError(err.message || "Errore");
      setSaving(false);
    }
  };

  return (
    <ModalC open={open} onClose={onClose} title={t.create_folder.title} sub={t.create_folder.sub} width={520}
      footer={
        <>
          <BtnC variant="ghost" onClick={onClose} disabled={saving}>{t.create_folder.cancel}</BtnC>
          <BtnC variant="primary" icon={<IcC.folderPlus />} disabled={!name.trim() || saving} onClick={handleCreate}>
            {saving ? (lang === "it" ? "Creazione…" : "Creating…") : t.create_folder.create}
          </BtnC>
        </>
      }>
      <div className="col" style={{ gap: 14 }}>
        {error && (
          <div style={{ color: "#B23A3A", fontSize: 13, padding: "8px 12px", background: "rgba(178,58,58,0.08)", borderRadius: 8 }}>
            {error}
          </div>
        )}
        <div className="field">
          <label className="label">{t.create_folder.name}</label>
          <input className="input" autoFocus value={name} onChange={(e) => setName(e.target.value)}
            placeholder={t.create_folder.name_ph}
            onKeyDown={(e) => { if (e.key === "Enter" && name.trim()) handleCreate(); }} />
        </div>
        <div className="field">
          <label className="label">{t.create_folder.parent}</label>
          <select className="input" value={parent} onChange={(e) => setParent(e.target.value)}>
            <option value="">📁 {t.create_folder.root}</option>
            {folders.map((f) => (
              <option key={f.id} value={f.id}>↳ {f.name}</option>
            ))}
          </select>
        </div>
        <div className="field">
          <div className="field-row">
            <label className="label">{t.create_folder.note}</label>
            <InfoC>{lang === "it" ? "Aggiunge una prima nota di contesto alla cartella." : "Adds an initial context note to the folder."}</InfoC>
          </div>
          <textarea className="input" placeholder={t.create_folder.note_ph} value={note} onChange={(e) => setNote(e.target.value)} />
        </div>
      </div>
    </ModalC>
  );
}

function UploadToast({ t, lang, upload, onOpenModal }) {
  const { files, phase, toastShow, toastDone, doneCount, hasError, activeFile, fmtSpeed, speeds, dismiss } = upload;
  if (!toastShow) return null;

  const totalProgress = files.length > 0
    ? Math.round(files.reduce((s, f) => s + (f.done ? 100 : f.progress), 0) / files.length)
    : 0;

  return (
    <div className="upload-toast">
      <div className="upload-toast-inner" data-tone={toastDone ? "ok" : hasError ? "err" : ""} onClick={onOpenModal}>
        {toastDone ? <IcC.check style={{ width: 18, height: 18, color: "#1F7A4D", flexShrink: 0 }} />
          : <IcC.cloud style={{ width: 18, height: 18, flexShrink: 0 }} />}
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 13, fontWeight: 500 }}>
            {toastDone
              ? (lang === "it" ? "Tutti i file caricati" : "All files uploaded")
              : hasError
                ? (lang === "it" ? `${doneCount} di ${files.length} file · ${files.filter(f => f.error).length} ${files.filter(f => f.error).length === 1 ? 'errore' : 'errori'}` : `${doneCount} of ${files.length} files · ${files.filter(f => f.error).length} ${files.filter(f => f.error).length === 1 ? 'error' : 'errors'}`)
                : (lang === "it" ? `${doneCount} di ${files.length} file` : `${doneCount} of ${files.length} files`)}
          </div>
          {!toastDone && activeFile && (
            <div style={{ fontSize: 11.5, color: "var(--ink-soft)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
              {activeFile.name}
              {!activeFile.done && !activeFile.error && speeds.length > 0 && (
                <span> · {fmtSpeed(speeds[files.indexOf(activeFile)] || 0)}</span>
              )}
            </div>
          )}
        </div>
        {!toastDone && !hasError && (
          <div className="progress" style={{ width: 100, flexShrink: 0 }}>
            <span style={{ width: totalProgress + "%" }} />
          </div>
        )}
        {toastDone && <div style={{ fontSize: 11, color: "var(--ink-soft)", flexShrink: 0 }}>OK</div>}
        {(toastDone || hasError) && (
          <button className="iconbtn" style={{ flexShrink: 0 }}
            onClick={(e) => { e.stopPropagation(); dismiss(); }}>
            <IcC.x />
          </button>
        )}
      </div>
    </div>
  );
}

function ConfirmModal({ open, title, message, confirmLabel, danger, onConfirm, onCancel, lang }) {
  if (!open) return null;
  return (
    <div className="modal-veil" onClick={onCancel}>
      <div className="modal" style={{ maxWidth: 420 }} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div>
            <h3 style={{ margin: 0 }}>{title}</h3>
            {message && <p style={{ margin: "6px 0 0", color: "var(--ink-soft)", fontSize: 13.5, lineHeight: 1.5 }}>{message}</p>}
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn" data-variant="ghost" onClick={onCancel}>
            {lang === "it" ? "Annulla" : "Cancel"}
          </button>
          <button className="btn" data-variant={danger ? "danger" : "primary"}
            style={danger ? { background: "#B23A3A", color: "#fff", borderColor: "#B23A3A" } : {}}
            onClick={onConfirm}>
            {confirmLabel || (lang === "it" ? "Conferma" : "Confirm")}
          </button>
        </div>
      </div>
    </div>
  );
}

window.UploadModal = UploadModal;
window.UploadToast = UploadToast;
window.CreateFolderModal = CreateFolderModal;
window.ConfirmModal = ConfirmModal;
