/* feedback.jsx
 *
 * Feedback widget — a small footer rendered on every view that opens a modal
 * for users to send suggestions, complaints, bug reports, etc.
 *
 * The submit path is mailto:-based. We don't run our own SMTP and don't relay
 * through a backend; clicking Submit opens the user's mail client with the
 * message prefilled and sends as the user. This is intentional:
 *   - Zero backend, zero API keys to manage, zero spam-handling burden.
 *   - The user can see and edit what they're about to send before it leaves.
 *   - Replies from us come from a real human reading a real inbox, which is
 *     better than a "noreply@" robot anyway.
 * Tradeoff: it requires a configured mail client on the user's device, but
 * mobile defaults handle this well and desktop Gmail Web works via the
 * `https://mail.google.com/mail/?...` fallback some browsers offer.
 *
 * Two variants exposed:
 *   <window.FeedbackFooter />       — site-wide footer with "Feedback" link
 *   <window.FeedbackRequestCertBtn /> — chooser-screen button for cert requests
 *
 * Both open a modal. The cert-request variant routes to a different email
 * (requests@cyberstudy.io) and uses a simpler form (no cert/pages context).
 *
 * Sign-in gating: both variants require an authenticated session. Clicking
 * while logged out shows a sign-in prompt with links to login / signup.
 *
 * Tab-name resolution: the form needs to know which tab the user is on so it
 * can prefill "pages this applies to". We read it from window.location.pathname
 * since the router writes there. Fallback to 'home'.
 */
(function () {
  "use strict";

  // Backend endpoints — send via server, not mailto:. Both endpoints require
  // an authenticated session; the modal already gates on isLoggedIn so
  // unauthenticated users see the SignInPrompt instead.
  const FEEDBACK_ENDPOINT = "/api/feedback";
  const CERT_REQUEST_ENDPOINT = "/api/cert-request";

  // Tab list shown in the multi-select. Order matches the top-bar tabs.
  // If new tabs are added to the app, append them here. Kept static (rather
  // than derived from app.jsx's tab list) because some tabs aren't user-
  // navigable on every cert and we want consistent feedback context labels.
  const ALL_TABS = [
    { id: "home",        label: "Home" },
    { id: "learn",       label: "Learn" },
    { id: "practice",    label: "Practice" },
    { id: "progress",    label: "Progress" },
    { id: "final-exam",  label: "Final Exam" },
    { id: "notes",       label: "Notes" },
    { id: "chooser",     label: "Cert Chooser" },
    { id: "other",       label: "Other / Not Applicable" },
  ];

  const TYPES = [
    { id: "suggestion",  label: "Suggestion" },
    { id: "request",     label: "Request" },
    { id: "complaint",   label: "Complaint" },
    { id: "question",    label: "Question" },
    { id: "bug",         label: "Bug Report" },
    { id: "other",       label: "Other" },
  ];

  // Cert track list is read from window.EXAMS (the single source of truth
  // for which certs exist on the site). Adding a new cert to exams.js
  // automatically surfaces it in the feedback form dropdown — no edit here
  // required. See docs/ADD_NEW_EXAM.md.
  function getCerts() {
    const exams = window.EXAMS || [];
    return exams.map(e => ({ id: e.id, label: e.label }));
  }

  // ── Helpers ─────────────────────────────────────────────────────────────

  function getCurrentTabId() {
    const path = (window.location.pathname || "").replace(/^\/+|\/+$/g, "");
    if (!path) return "home";
    // Known tabs from the router; anything else maps to "other".
    const known = new Set(["home", "learn", "practice", "progress", "final-exam", "notes"]);
    return known.has(path) ? path : "other";
  }

  function getCurrentCert() {
    const cert = window.UserData && window.UserData.getCertMode
      ? window.UserData.getCertMode()
      : null;
    if (cert) return cert;
    // If chooser is showing (no cert picked yet), default to the first cert
    // in the registry as a best-effort. The form lets the user override.
    const exams = window.EXAMS || [];
    return exams.length ? exams[0].id : "secplus";
  }

  function getCertLabel(certId) {
    // Prefer the helper exposed by exams.js when available — keeps cert
    // labels consistent across the whole app.
    if (window.getExamLabel) return window.getExamLabel(certId);
    const c = getCerts().find(x => x.id === certId);
    return c ? c.label : certId;
  }

  function getTabLabel(tabId) {
    const t = ALL_TABS.find(x => x.id === tabId);
    return t ? t.label : tabId;
  }

  function getTypeLabel(typeId) {
    const t = TYPES.find(x => x.id === typeId);
    return t ? t.label : typeId;
  }

  // Submit a payload to one of our backend feedback endpoints. Uses the
  // AuthStore's api() helper so the JWT bearer token is attached. Returns
  // { ok: bool, message: string } from the server, or { ok: false,
  // message: <network-level error> } on transport failure.
  async function submitToApi(endpoint, payload) {
    if (!window.AuthStore || !window.AuthStore.api) {
      return { ok: false, message: "Not signed in." };
    }
    try {
      const result = await window.AuthStore.api(endpoint, {
        method: "POST",
        body: JSON.stringify(payload),
      });
      // The api() helper returns the parsed JSON body; our endpoints
      // always return { ok, message }.
      return result || { ok: false, message: "Empty response from server." };
    } catch (err) {
      // api() throws on HTTP non-2xx. Surface a generic network error.
      return {
        ok: false,
        message: (err && err.message) ? err.message : "Network error. Please try again.",
      };
    }
  }

  // ── Modal shell (reusable for both variants) ────────────────────────────

  function Modal({ open, onClose, children, ariaLabel }) {
    React.useEffect(() => {
      if (!open) return;
      const onKey = (e) => { if (e.key === "Escape") onClose(); };
      document.addEventListener("keydown", onKey);
      // Prevent background scroll while modal is open.
      const prevOverflow = document.body.style.overflow;
      document.body.style.overflow = "hidden";
      return () => {
        document.removeEventListener("keydown", onKey);
        document.body.style.overflow = prevOverflow;
      };
    }, [open, onClose]);

    if (!open) return null;

    return React.createElement(
      "div",
      {
        className: "fb-modal-backdrop",
        onClick: (e) => { if (e.target === e.currentTarget) onClose(); },
        role: "dialog",
        "aria-modal": "true",
        "aria-label": ariaLabel || "Dialog",
      },
      React.createElement(
        "div",
        { className: "fb-modal", onClick: (e) => e.stopPropagation() },
        React.createElement(
          "button",
          { className: "fb-modal-close", onClick: onClose, "aria-label": "Close" },
          "×"
        ),
        children
      )
    );
  }

  // ── Sign-in prompt (shown when logged-out user opens any feedback modal) ─

  function SignInPrompt({ onClose, action }) {
    function goLogin() {
      onClose();
      if (window.AuthNav && window.AuthNav.setView) window.AuthNav.setView("login");
    }
    function goSignup() {
      onClose();
      if (window.AuthNav && window.AuthNav.setView) window.AuthNav.setView("signup");
    }
    return React.createElement(
      "div",
      { className: "fb-signin-prompt" },
      React.createElement("h2", null, "Sign in required"),
      React.createElement(
        "p",
        null,
        "To ", action || "send feedback", " you'll need to be signed in. This lets us reach back if we have questions, and helps us keep this channel useful instead of spam."
      ),
      React.createElement(
        "div",
        { className: "fb-actions" },
        React.createElement(
          "button",
          { className: "btn btn-primary", onClick: goLogin },
          "Sign in"
        ),
        React.createElement(
          "button",
          { className: "btn btn-secondary", onClick: goSignup },
          "Create an account"
        )
      )
    );
  }

  // ── Feedback form (full version with all fields) ────────────────────────

  function FeedbackForm({ onClose }) {
    const user = (window.AuthStore && window.AuthStore.user) || {};
    const userEmail = user.email || "";
    const userName = user.name || user.username || userEmail;

    const initialTab = getCurrentTabId();
    const initialCert = getCurrentCert();

    const [type, setType] = React.useState("suggestion");
    const [cert, setCert] = React.useState(initialCert);
    const [pages, setPages] = React.useState(new Set([initialTab]));
    const [subjectSuffix, setSubjectSuffix] = React.useState("");
    const [message, setMessage] = React.useState("");
    const [wantResponse, setWantResponse] = React.useState(false);
    // Submission state machine: 'idle' → 'sending' → 'sent' (auto-close after 2s)
    //                                            └→ 'error' (stays on form, user can retry)
    const [status, setStatus] = React.useState("idle");
    const [errorMsg, setErrorMsg] = React.useState("");

    // Subject prefix is auto-computed from type/cert/pages and is NOT editable.
    // The user only types the descriptive suffix in the input below the prefix.
    // Keeps the context tag consistent across submissions so we can triage by
    // it server-side (eventually) and prevents accidentally deleting the tag.
    const subjectPrefix = React.useMemo(() => {
      const tabStr = pages.size === 1
        ? getTabLabel([...pages][0])
        : pages.size > 1 ? `${pages.size} pages` : "general";
      return `[${getCertLabel(cert)} / ${tabStr}] ${getTypeLabel(type)}:`;
    }, [type, cert, pages]);

    function togglePage(pageId) {
      setPages(prev => {
        const next = new Set(prev);
        if (next.has(pageId)) next.delete(pageId);
        else next.add(pageId);
        return next;
      });
    }

    async function handleSubmit() {
      if (status === "sending") return; // guard double-clicks
      if (!message.trim()) {
        setErrorMsg("Please enter a message before sending.");
        setStatus("error");
        return;
      }
      if (pages.size === 0) {
        setErrorMsg("Please select at least one page this applies to (or choose Other).");
        setStatus("error");
        return;
      }

      setStatus("sending");
      setErrorMsg("");

      const payload = {
        type: getTypeLabel(type),
        cert,
        pages: [...pages].map(getTabLabel),
        subject_prefix: subjectPrefix,
        subject_suffix: subjectSuffix,
        message,
        want_response: wantResponse,
      };

      const result = await submitToApi(FEEDBACK_ENDPOINT, payload);
      if (result.ok) {
        setStatus("sent");
        // Auto-close after 2s so the user sees the confirmation.
        setTimeout(onClose, 2000);
      } else {
        setErrorMsg(result.message || "Couldn't send. Please try again.");
        setStatus("error");
      }
    }

    return React.createElement(
      "div",
      { className: "fb-form" },
      React.createElement("h2", null, "Send feedback"),
      React.createElement(
        "p",
        { className: "fb-form-intro" },
        "Bug, suggestion, request, anything — we read every one. We'll reach back if you ask us to."
      ),

      // Type
      React.createElement(
        "div",
        { className: "fb-field" },
        React.createElement("label", { className: "fb-label" }, "Type"),
        React.createElement(
          "select",
          { className: "fb-select", value: type, onChange: (e) => setType(e.target.value) },
          TYPES.map(t => React.createElement("option", { key: t.id, value: t.id }, t.label))
        )
      ),

      // Cert track
      React.createElement(
        "div",
        { className: "fb-field" },
        React.createElement("label", { className: "fb-label" }, "Cert track"),
        React.createElement(
          "select",
          { className: "fb-select", value: cert, onChange: (e) => setCert(e.target.value) },
          getCerts().map(c => React.createElement("option", { key: c.id, value: c.id }, c.label))
        )
      ),

      // Pages (multi-select via checkboxes)
      React.createElement(
        "div",
        { className: "fb-field" },
        React.createElement(
          "label",
          { className: "fb-label" },
          "Pages this applies to (select all that apply)"
        ),
        React.createElement(
          "div",
          { className: "fb-checkbox-grid" },
          ALL_TABS.map(t => React.createElement(
            "label",
            { key: t.id, className: "fb-checkbox" },
            React.createElement("input", {
              type: "checkbox",
              checked: pages.has(t.id),
              onChange: () => togglePage(t.id),
            }),
            React.createElement("span", null, t.label)
          ))
        )
      ),

      // Subject — auto-prefix (uneditable) + user-typed suffix
      React.createElement(
        "div",
        { className: "fb-field" },
        React.createElement("label", { className: "fb-label" }, "Subject"),
        React.createElement(
          "div",
          { className: "fb-subject-row" },
          React.createElement(
            "span",
            { className: "fb-subject-prefix", title: "Auto-generated from Type / Cert / Pages" },
            subjectPrefix
          ),
          React.createElement("input", {
            type: "text",
            className: "fb-input fb-subject-suffix",
            value: subjectSuffix,
            onChange: (e) => setSubjectSuffix(e.target.value),
            placeholder: "Short summary of your message",
          })
        )
      ),

      // Message
      React.createElement(
        "div",
        { className: "fb-field" },
        React.createElement("label", { className: "fb-label" }, "Message"),
        React.createElement("textarea", {
          className: "fb-textarea",
          rows: 7,
          value: message,
          onChange: (e) => setMessage(e.target.value),
          placeholder: "Tell us what's on your mind…",
        })
      ),

      // Want response
      React.createElement(
        "div",
        { className: "fb-field" },
        React.createElement(
          "label",
          { className: "fb-checkbox fb-checkbox-large" },
          React.createElement("input", {
            type: "checkbox",
            checked: wantResponse,
            onChange: (e) => setWantResponse(e.target.checked),
          }),
          React.createElement(
            "span",
            null,
            "I'd like a response — okay to reach me at ",
            React.createElement("strong", null, userEmail)
          )
        )
      ),

      // Status banner (success / error)
      status === "sent" && React.createElement(
        "div",
        { className: "fb-status fb-status-ok" },
        "✓ Thanks — we got your message."
      ),
      status === "error" && React.createElement(
        "div",
        { className: "fb-status fb-status-err" },
        errorMsg || "Something went wrong. Please try again."
      ),

      // Actions
      React.createElement(
        "div",
        { className: "fb-actions" },
        React.createElement(
          "button",
          {
            className: "btn btn-primary",
            onClick: handleSubmit,
            disabled: status === "sending" || status === "sent",
          },
          status === "sending" ? "Sending…" : status === "sent" ? "Sent ✓" : "Send feedback"
        ),
        React.createElement(
          "button",
          { className: "btn btn-secondary", onClick: onClose, disabled: status === "sending" },
          status === "sent" ? "Close" : "Cancel"
        )
      )
    );
  }

  // ── Cert request form (simpler — single textarea + submit) ──────────────

  // RequestForm renders the same modal shape for either "request a cert" or
  // "request a career path" flows. The two are nearly identical user-facing
  // — free-form name + optional reason + optional response opt-in — and the
  // backend uses one endpoint (/api/cert-request) with a request_type field
  // to triage in the requests@ inbox.
  //
  // kind = "cert" | "career_path"
  function RequestForm({ onClose, kind }) {
    const isCareer = kind === "career_path";
    const user = (window.AuthStore && window.AuthStore.user) || {};
    const userEmail = user.email || "";
    const userName = user.name || user.username || userEmail;

    const labels = isCareer ? {
      heading: "Request a new career path",
      intro: "Want us to add a career path that isn't here yet? Tell us which one and why it matters to you. We prioritize new paths based on requests.",
      fieldLabel: "Which career path?",
      fieldPlaceholder: "e.g. DevOps Engineer, Database Administrator, Game Developer",
      reasonPlaceholder: "What kind of role are you aiming for? What certs would matter most for it?",
      validationMissing: "Please enter which career path you'd like us to add.",
    } : {
      heading: "Request a new certification",
      intro: "Want us to add a cert track that isn't here? Let us know which one and what you'd hope to study for. We prioritize tracks based on requests.",
      fieldLabel: "Which certification?",
      fieldPlaceholder: "e.g. Network+, AWS SAA-C03, CISSP",
      reasonPlaceholder: "Why this cert, when you plan to take it, what topics matter most to you, etc.",
      validationMissing: "Please enter which cert you'd like us to add.",
    };

    const [itemName, setItemName] = React.useState("");
    const [reason, setReason] = React.useState("");
    const [wantResponse, setWantResponse] = React.useState(false);
    const [status, setStatus] = React.useState("idle");
    const [errorMsg, setErrorMsg] = React.useState("");

    async function handleSubmit() {
      if (status === "sending") return;
      if (!itemName.trim()) {
        setErrorMsg(labels.validationMissing);
        setStatus("error");
        return;
      }
      setStatus("sending");
      setErrorMsg("");
      const payload = {
        cert_name: itemName,        // backend reuses cert_name field for both kinds
        reason,
        want_response: wantResponse,
        request_type: isCareer ? "career_path" : "cert",
      };
      const result = await submitToApi(CERT_REQUEST_ENDPOINT, payload);
      if (result.ok) {
        setStatus("sent");
        setTimeout(onClose, 2000);
      } else {
        setErrorMsg(result.message || "Couldn't send. Please try again.");
        setStatus("error");
      }
    }

    return React.createElement(
      "div",
      { className: "fb-form" },
      React.createElement("h2", null, labels.heading),
      React.createElement(
        "p",
        { className: "fb-form-intro" },
        labels.intro
      ),

      React.createElement(
        "div",
        { className: "fb-field" },
        React.createElement("label", { className: "fb-label" }, labels.fieldLabel),
        React.createElement("input", {
          type: "text",
          className: "fb-input",
          value: itemName,
          onChange: (e) => setItemName(e.target.value),
          placeholder: labels.fieldPlaceholder,
        })
      ),

      React.createElement(
        "div",
        { className: "fb-field" },
        React.createElement(
          "label",
          { className: "fb-label" },
          "Anything else? (optional)"
        ),
        React.createElement("textarea", {
          className: "fb-textarea",
          rows: 5,
          value: reason,
          onChange: (e) => setReason(e.target.value),
          placeholder: labels.reasonPlaceholder,
        })
      ),

      React.createElement(
        "div",
        { className: "fb-field" },
        React.createElement(
          "label",
          { className: "fb-checkbox fb-checkbox-large" },
          React.createElement("input", {
            type: "checkbox",
            checked: wantResponse,
            onChange: (e) => setWantResponse(e.target.checked),
          }),
          React.createElement(
            "span",
            null,
            "I'd like a response — okay to reach me at ",
            React.createElement("strong", null, userEmail)
          )
        )
      ),

      // Status banner
      status === "sent" && React.createElement(
        "div",
        { className: "fb-status fb-status-ok" },
        "✓ Thanks — we got your request."
      ),
      status === "error" && React.createElement(
        "div",
        { className: "fb-status fb-status-err" },
        errorMsg || "Something went wrong. Please try again."
      ),

      React.createElement(
        "div",
        { className: "fb-actions" },
        React.createElement(
          "button",
          {
            className: "btn btn-primary",
            onClick: handleSubmit,
            disabled: status === "sending" || status === "sent",
          },
          status === "sending" ? "Sending…" : status === "sent" ? "Sent ✓" : "Send request"
        ),
        React.createElement(
          "button",
          { className: "btn btn-secondary", onClick: onClose, disabled: status === "sending" },
          status === "sent" ? "Close" : "Cancel"
        )
      )
    );
  }

  // Backwards-compatible cert-request wrapper. Existing FeedbackRequestCertBtn
  // and any other callers that import CertRequestForm continue to work.
  function CertRequestForm({ onClose }) {
    return React.createElement(RequestForm, { onClose, kind: "cert" });
  }

  // Career-path request wrapper — used by the Career Planner catalog page.
  function CareerPathRequestForm({ onClose }) {
    return React.createElement(RequestForm, { onClose, kind: "career_path" });
  }

  // ── Public components ───────────────────────────────────────────────────

  /** Site-wide footer with "Send feedback" link. Renders on every view. */
  function FeedbackFooter() {
    const [open, setOpen] = React.useState(false);
    const isLoggedIn = !!(window.AuthStore && window.AuthStore.isLoggedIn);

    return React.createElement(
      React.Fragment,
      null,
      React.createElement(
        "footer",
        { className: "fb-footer" },
        React.createElement(
          "button",
          { className: "fb-footer-link", onClick: () => setOpen(true) },
          "Send feedback"
        )
      ),
      React.createElement(
        Modal,
        {
          open,
          onClose: () => setOpen(false),
          ariaLabel: isLoggedIn ? "Send feedback" : "Sign in required",
        },
        isLoggedIn
          ? React.createElement(FeedbackForm, { onClose: () => setOpen(false) })
          : React.createElement(SignInPrompt, { onClose: () => setOpen(false), action: "send feedback" })
      )
    );
  }

  /** Chooser-screen button: "Request a new certification". */
  function FeedbackRequestCertBtn() {
    const [open, setOpen] = React.useState(false);
    const isLoggedIn = !!(window.AuthStore && window.AuthStore.isLoggedIn);

    return React.createElement(
      React.Fragment,
      null,
      React.createElement(
        "button",
        { className: "fb-request-cert-btn", onClick: () => setOpen(true) },
        "+ Request a new certification"
      ),
      React.createElement(
        Modal,
        {
          open,
          onClose: () => setOpen(false),
          ariaLabel: isLoggedIn ? "Request a new certification" : "Sign in required",
        },
        isLoggedIn
          ? React.createElement(CertRequestForm, { onClose: () => setOpen(false) })
          : React.createElement(SignInPrompt, { onClose: () => setOpen(false), action: "request a new certification" })
      )
    );
  }

  window.FeedbackFooter = FeedbackFooter;
  window.FeedbackRequestCertBtn = FeedbackRequestCertBtn;
  window.FeedbackModal = Modal;
  window.FeedbackSignInPrompt = SignInPrompt;
  window.CareerPathRequestForm = CareerPathRequestForm;
})();
