/* 登录 / 注册 / 找回密码 三个页面共用的前端逻辑
 *
 * 职责：图形验证码刷新、手机验证码倒计时、表单提交与错误提示。
 * 依赖：仅原生 JS，无任何外部库（断网可用）。
 */
(function (global) {
  "use strict";

  var CAPTCHA_URL = "/api/auth/captcha";
  var SMS_URL = "/api/auth/sms";

  /* ---------- 小工具 ---------- */
  function $(id) { return document.getElementById(id); }

  function showMsg(el, kind, text) {
    if (!el) return;
    el.className = "msg " + (kind === "ok" ? "is-ok" : kind === "info" ? "is-info" : "is-error");
    el.textContent = text;
  }

  function hideMsg(el) { if (el) el.className = "msg"; }

  function post(url, payload) {
    return fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/json; charset=utf-8" },
      body: JSON.stringify(payload || {})
    }).then(function (res) {
      return res.json().then(function (data) { return { ok: res.ok, status: res.status, data: data || {} }; });
    });
  }

  /** 只接受站内相对路径，避免开放重定向 */
  function safeNext(fallback) {
    var params = new URLSearchParams(global.location.search);
    var next = params.get("next") || "";
    if (!next || next.charAt(0) !== "/" || next.charAt(1) === "/") return fallback || "/";
    return next;
  }

  /* ---------- 图形验证码 ---------- */
  var Captcha = {
    id: "",
    /** 拉取一张新验证码：答案在服务端，id 通过响应头带回 */
    refresh: function (imgEl) {
      if (!imgEl) return Promise.resolve("");
      var url = CAPTCHA_URL + "?_=" + Date.now();
      return fetch(url, { headers: { Accept: "image/png" }, cache: "no-store" })
        .then(function (res) {
          Captcha.id = res.headers.get("X-Captcha-Id") || "";
          return res.blob();
        })
        .then(function (blob) {
          if (imgEl._objectUrl) URL.revokeObjectURL(imgEl._objectUrl);
          imgEl._objectUrl = URL.createObjectURL(blob);
          imgEl.src = imgEl._objectUrl;
          return Captcha.id;
        })
        .catch(function () { return ""; });
    },
    /** 绑定点击刷新 */
    bind: function (imgEl, hintEl) {
      if (!imgEl) return;
      imgEl.addEventListener("click", function () {
        Captcha.refresh(imgEl);
        if (hintEl) hintEl.textContent = "已换一张";
      });
      Captcha.refresh(imgEl);
    },
    /** 校验失败后自动换一张，避免用户重复提交同一个失效验证码 */
    renew: function (imgEl) { return Captcha.refresh(imgEl); }
  };

  /* ---------- 手机验证码（含 60 秒倒计时） ---------- */
  var Sms = {
    /** 发送验证码；返回 Promise，成功时 resolve 服务端返回体 */
    send: function (options) {
      var payload = {
        phone: options.phone,
        scene: options.scene || "register",
        captcha_id: Captcha.id,
        captcha_code: options.captchaCode
      };
      return post(SMS_URL, payload);
    },
    /** 开始倒计时，期间禁用按钮 */
    startCountdown: function (buttonEl, seconds) {
      var left = seconds || 60;
      var original = buttonEl.textContent;
      buttonEl.disabled = true;
      buttonEl.textContent = left + " 秒后重发";
      var timer = setInterval(function () {
        left -= 1;
        if (left <= 0) {
          clearInterval(timer);
          buttonEl.disabled = false;
          buttonEl.textContent = original;
          return;
        }
        buttonEl.textContent = left + " 秒后重发";
      }, 1000);
      return timer;
    }
  };

  /* ---------- 表单校验 ---------- */
  var Validate = {
    phone: function (value) { return /^1[3-9]\d{9}$/.test(String(value || "").trim()); },
    username: function (value) { return /^[A-Za-z][A-Za-z0-9_]{2,19}$/.test(String(value || "").trim()); },
    password: function (value) { return String(value || "").length >= 6; }
  };

  function focusFirstError(ids) {
    for (var i = 0; i < ids.length; i += 1) {
      var el = $(ids[i]);
      if (el && el.classList.contains("is-error") && typeof el.focus === "function") { el.focus(); return; }
    }
  }

  function markError(el, on) {
    if (!el) return;
    if (on) el.classList.add("is-error"); else el.classList.remove("is-error");
  }

  global.AuthUI = {
    $: $, showMsg: showMsg, hideMsg: hideMsg, post: post, safeNext: safeNext,
    Captcha: Captcha, Sms: Sms, Validate: Validate,
    markError: markError, focusFirstError: focusFirstError
  };
})(window);
