// NextGen Ranking — visitor feedback modal.
// Footer link opens a bottom-sheet modal that POSTs to /api/feedback.
// Mirrors profile.jsx modal mechanics: ESC closes, body scroll lock,
// role="dialog" + aria-modal, sticky head with close button.
//
// Spam defense is shared with the Function: hidden honeypot input +
// Cloudflare Turnstile widget rendered into a host div in a useEffect.

// Public Turnstile site key. Safe to commit — Cloudflare validates the
// hostname allowlist server-side, so the key is useless on a foreign
// origin. The matching secret lives in CF Pages env vars.
const TURNSTILE_SITE_KEY = "0x4AAAAAADSodXmg3efxyVBw";

const FEEDBACK_CATEGORIES = ["bug", "data", "suggestion", "other"];

function FeedbackButton({ t }) {
  const [open, setOpen] = React.useState(false);
  const triggerRef = React.useRef(null);
  const F = t.dict.feedback || {};

  const handleClose = React.useCallback(() => {
    setOpen(false);
    // Restore focus to the trigger after the modal unmounts.
    setTimeout(() => { if (triggerRef.current) triggerRef.current.focus(); }, 0);
  }, []);

  return (
    <React.Fragment>
      <button
        ref={triggerRef}
        type="button"
        className="feedback-modal__trigger"
        aria-haspopup="dialog"
        aria-expanded={open}
        onClick={() => setOpen(true)}
      >
        {F.trigger || "Send feedback"}
      </button>
      {open && <FeedbackModal t={t} onClose={handleClose} />}
    </React.Fragment>
  );
}

function FeedbackModal({ t, onClose }) {
  const F = t.dict.feedback || {};

  const [status,   setStatus]   = React.useState("idle"); // idle | sending | success | error
  const [category, setCategory] = React.useState("bug");
  const [message,  setMessage]  = React.useState("");
  const [name,     setName]     = React.useState("");
  const [email,    setEmail]    = React.useState("");
  const [hp,       setHp]       = React.useState("");
  const [token,    setToken]    = React.useState("");
  const [errorKey, setErrorKey] = React.useState("");
  const [fieldError, setFieldError] = React.useState("");

  const turnstileRef = React.useRef(null);
  const firstFieldRef = React.useRef(null);
  const mountedRef = React.useRef(true);

  // ESC closes + body scroll lock. Mirrors profile.jsx.
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => {
      document.removeEventListener("keydown", onKey);
      document.body.style.overflow = prevOverflow;
    };
  }, [onClose]);

  // Focus the first field on open.
  React.useEffect(() => {
    if (firstFieldRef.current) firstFieldRef.current.focus();
  }, []);

  // Track mount for the fetch unmount-guard.
  React.useEffect(() => {
    mountedRef.current = true;
    return () => { mountedRef.current = false; };
  }, []);

  // Turnstile widget lifecycle. Renders into the host div once the
  // global is available; removes the widget on unmount to avoid
  // orphan iframes if the modal is reopened.
  React.useEffect(() => {
    let widgetId = null;
    let cancelled = false;

    const tryRender = () => {
      if (cancelled) return;
      const ts = window.turnstile;
      if (!ts || !turnstileRef.current) {
        // Turnstile script still loading; retry shortly.
        setTimeout(tryRender, 120);
        return;
      }
      widgetId = ts.render(turnstileRef.current, {
        sitekey:  TURNSTILE_SITE_KEY,
        theme:    "light",
        callback:         (tok) => { if (!cancelled) setToken(tok || ""); },
        "error-callback": ()    => { if (!cancelled) setToken(""); },
        "expired-callback": ()  => { if (!cancelled) setToken(""); },
      });
    };
    tryRender();

    return () => {
      cancelled = true;
      const ts = window.turnstile;
      if (ts && widgetId != null) {
        try { ts.remove(widgetId); } catch (_) { /* widget already gone */ }
      }
    };
  }, []);

  const reset = () => {
    setCategory("bug");
    setMessage("");
    setName("");
    setEmail("");
    setHp("");
    setToken("");
    setErrorKey("");
    setFieldError("");
  };

  const validateClient = () => {
    if (!message.trim()) {
      setFieldError("message");
      setErrorKey("error_validation");
      return false;
    }
    if (message.length > 5000) {
      setFieldError("message");
      setErrorKey("error_validation");
      return false;
    }
    if (name.length > 120) {
      setFieldError("name");
      setErrorKey("error_validation");
      return false;
    }
    if (!email.trim() || !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email.trim())) {
      setFieldError("email");
      setErrorKey("error_validation");
      return false;
    }
    if (!token) {
      setFieldError("turnstile");
      setErrorKey("error_turnstile");
      return false;
    }
    setFieldError("");
    setErrorKey("");
    return true;
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (status === "sending") return;
    if (!validateClient()) return;

    setStatus("sending");

    let resp;
    try {
      resp = await fetch("/api/feedback", {
        method:  "POST",
        headers: { "Content-Type": "application/json" },
        body:    JSON.stringify({
          category, message, name, email,
          lang: t.lang || window.DEFAULT_LANG,
          token, hp,
        }),
      });
    } catch (_) {
      if (!mountedRef.current) return;
      setErrorKey("error_send_failed");
      setStatus("error");
      return;
    }
    if (!mountedRef.current) return;

    let data = null;
    try { data = await resp.json(); } catch (_) { data = null; }
    if (!mountedRef.current) return;

    if (resp.ok && data && data.ok) {
      setStatus("success");
      return;
    }
    const code = (data && data.error) || "send_failed";
    if (code === "validation")   setErrorKey("error_validation");
    else if (code === "turnstile") setErrorKey("error_turnstile");
    else                           setErrorKey("error_send_failed");
    setStatus("error");
  };

  const onBackdropClick = (e) => {
    if (e.target === e.currentTarget) onClose();
  };

  const titleId = "feedback-modal-title";

  return (
    <div className="feedback-modal" role="dialog" aria-modal="true" aria-labelledby={titleId}>
      <div
        className="feedback-modal__backdrop"
        aria-hidden="true"
        onClick={onBackdropClick}
      />
      <div className="feedback-modal__panel" role="document">
        <header className="feedback-modal__head">
          <div id={titleId} className="feedback-modal__title">
            {F.title || "Send us feedback"}
          </div>
          <button
            type="button"
            className="feedback-modal__close"
            onClick={onClose}
            aria-label={F.close || "Close"}
          >
            ×
          </button>
        </header>

        {status === "success" ? (
          <div className="feedback-modal__success">
            <div className="feedback-modal__success-title">
              {F.success_title || "Thanks for the message!"}
            </div>
            <div className="feedback-modal__success-body">
              {F.success_body || "It's on its way to the operator's inbox."}
            </div>
            <div className="feedback-modal__success-actions">
              <button
                type="button"
                className="feedback-form__submit"
                onClick={() => { reset(); setStatus("idle"); }}
              >
                {F.send_another || "Send another"}
              </button>
              <button
                type="button"
                className="feedback-modal__close-text"
                onClick={onClose}
              >
                {F.close || "Close"}
              </button>
            </div>
          </div>
        ) : (
          <form className="feedback-form" onSubmit={handleSubmit} noValidate>
            <div className="feedback-form__field">
              <label htmlFor="feedback-category" className="feedback-form__label">
                {F.category_label || "What's this about?"}
              </label>
              <select
                id="feedback-category"
                ref={firstFieldRef}
                className="feedback-form__select"
                value={category}
                onChange={(e) => setCategory(e.target.value)}
                disabled={status === "sending"}
              >
                {FEEDBACK_CATEGORIES.map(c => (
                  <option key={c} value={c}>
                    {(F.category && F.category[c]) || c}
                  </option>
                ))}
              </select>
            </div>

            <div className="feedback-form__field">
              <label htmlFor="feedback-message" className="feedback-form__label">
                {F.message || "Message"}
              </label>
              <textarea
                id="feedback-message"
                className={"feedback-form__textarea" + (fieldError === "message" ? " feedback-form__textarea--error" : "")}
                value={message}
                onChange={(e) => setMessage(e.target.value)}
                placeholder={F.message_placeholder || ""}
                rows={6}
                maxLength={5000}
                disabled={status === "sending"}
                aria-describedby={fieldError === "message" ? "feedback-error" : undefined}
                aria-invalid={fieldError === "message" ? "true" : undefined}
                required
              />
            </div>

            <div className="feedback-form__row">
              <div className="feedback-form__field">
                <label htmlFor="feedback-name" className="feedback-form__label">
                  {F.name || "Name"} <span className="feedback-form__hint">{F.optional || "optional"}</span>
                </label>
                <input
                  id="feedback-name"
                  type="text"
                  className="feedback-form__input"
                  value={name}
                  onChange={(e) => setName(e.target.value)}
                  maxLength={120}
                  autoComplete="name"
                  disabled={status === "sending"}
                />
              </div>
              <div className="feedback-form__field">
                <label htmlFor="feedback-email" className="feedback-form__label">
                  {F.email || "Email"}
                </label>
                <input
                  id="feedback-email"
                  type="email"
                  className={"feedback-form__input" + (fieldError === "email" ? " feedback-form__input--error" : "")}
                  value={email}
                  onChange={(e) => setEmail(e.target.value)}
                  maxLength={200}
                  autoComplete="email"
                  inputMode="email"
                  disabled={status === "sending"}
                  aria-describedby="feedback-email-help"
                  aria-invalid={fieldError === "email" ? "true" : undefined}
                  required
                />
                <div id="feedback-email-help" className="feedback-form__help">
                  {F.email_help || "We'll reply to this address."}
                </div>
              </div>
            </div>

            {/* Honeypot — real users never see or focus this. */}
            <div className="feedback-form__honeypot" aria-hidden="true">
              <label htmlFor="feedback-hp">Leave this empty</label>
              <input
                id="feedback-hp"
                type="text"
                tabIndex={-1}
                autoComplete="off"
                value={hp}
                onChange={(e) => setHp(e.target.value)}
              />
            </div>

            <div className="feedback-form__field">
              <div ref={turnstileRef} className="feedback-form__captcha" />
            </div>

            <div
              id="feedback-error"
              className="feedback-form__error"
              role="alert"
              aria-live="polite"
            >
              {errorKey ? (F[errorKey] || F.error_send_failed || "Something went wrong.") : ""}
            </div>

            <div className="feedback-form__actions">
              <button
                type="submit"
                className="feedback-form__submit"
                disabled={status === "sending"}
              >
                {status === "sending"
                  ? (F.sending || "Sending…")
                  : (F.submit || "Send")}
              </button>
            </div>
          </form>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { FeedbackButton, FeedbackModal });
