import { createContext, useCallback, useContext, useRef, useState } from "react";
import Icon from "./components/Icon";

/**
 * Rückfragen innerhalb der Anwendung statt über den Browser.
 *
 * `window.confirm` reißt den Benutzer aus der Oberfläche, zeigt den Hostnamen
 * und lässt sich weder gestalten noch beschriften. Der Dialog hier sieht aus wie
 * der Rest der Anwendung, kann eine Aktion benennen ("Löschen" statt "OK") und
 * gefährliche Schritte rot hervorheben.
 *
 * Aufruf bleibt so einfach wie vorher:
 *
 *     const confirm = useConfirm();
 *     if (!(await confirm({ title: "Gruppe löschen?", message: "…" }))) return;
 *
 * Mit `prompt: true` wird daraus eine Eingabe; aufgeloest wird dann der
 * eingetippte Text (oder `null` beim Abbrechen). Auch dafuer gilt der Grund von
 * oben: `window.prompt` sieht aus wie der Browser, nicht wie diese Anwendung.
 *
 *     const name = await confirm({ title: "Name?", prompt: true, defaultValue: "…" });
 */
const ConfirmContext = createContext(async () => false);

export function ConfirmProvider({ children }) {
  const [frage, setFrage] = useState(null);
  const [eingabe, setEingabe] = useState("");
  // Die Zusage des offenen Dialogs, damit `await confirm(...)` funktioniert.
  const antwort = useRef(null);

  const confirm = useCallback((optionen) => {
    const gestellt = typeof optionen === "string" ? { message: optionen } : optionen;
    setFrage(gestellt);
    setEingabe(gestellt.defaultValue ?? "");
    return new Promise((resolve) => {
      antwort.current = resolve;
    });
  }, []);

  function schliessen(ergebnis) {
    setFrage(null);
    antwort.current?.(ergebnis);
    antwort.current = null;
  }

  /** Bei einer Eingabe zaehlt der Text, sonst wie bisher true/false. */
  function bestaetigen() {
    if (!frage?.prompt) { schliessen(true); return; }
    const text = eingabe.trim();
    if (!text) return;   // Leer bestaetigen ergibt keinen Sinn
    schliessen(text);
  }

  return (
    <ConfirmContext.Provider value={confirm}>
      {children}
      {frage && (
        <div className="modal-backdrop"
             onClick={(e) => e.target === e.currentTarget && schliessen(frage.prompt ? null : false)}>
          <div className="modal" role="dialog" aria-modal="true">
            <div className="modal-head">
              <Icon name={frage.prompt ? "edit" : "alert"} size={18}
                    className={frage.danger ? "icon-danger" : ""} />
              <h2>{frage.title || "Bitte bestätigen"}</h2>
            </div>
            {frage.message && <p className="modal-body">{frage.message}</p>}
            {frage.prompt && (
              <div className="modal-body">
                {/* eslint-disable-next-line jsx-a11y/no-autofocus */}
                <input autoFocus value={eingabe} onChange={(e) => setEingabe(e.target.value)}
                       onKeyDown={(e) => {
                         if (e.key === "Enter") bestaetigen();
                         if (e.key === "Escape") schliessen(null);
                       }} />
              </div>
            )}
            <div className="btn-pair">
              <button type="button" className="btn" autoFocus={!frage.prompt}
                      onClick={() => schliessen(frage.prompt ? null : false)}>
                {frage.cancelLabel || "Abbrechen"}
              </button>
              <button type="button"
                      className={frage.danger ? "btn danger-solid" : "btn primary"}
                      disabled={frage.prompt && !eingabe.trim()}
                      onClick={bestaetigen}>
                {frage.confirmLabel || "Fortfahren"}
              </button>
            </div>
          </div>
        </div>
      )}
    </ConfirmContext.Provider>
  );
}

export function useConfirm() {
  return useContext(ConfirmContext);
}
