export type UploadProgress = {
  loaded: number;
  total: number;
};

export type AdminApiOptions = {
  csrf?: string;
};

const exactMessages: Record<string, string> = {
  "current password is invalid": "当前密码不正确",
  "new password is required": "新密码不能为空",
  "new password must be at least 8 characters": "新密码至少需要 8 位",
  "new password cannot be admin": "新密码不能为 admin",
  "new password must be different from current password": "新密码不能与当前密码相同",
  "invalid password or captcha": "密码或验证码不正确",
  "login required": "需要登录后继续操作",
  "csrf token required": "页面安全令牌已失效，请刷新后重试",
  "csrf token invalid": "页面安全令牌无效，请刷新后重试",
  "code is required": "缺少反馈编号",
  "revisionid is required": "请选择要恢复的历史版本",
  "post required": "该操作需要使用 POST 请求",
  "get required": "该操作需要使用 GET 请求",
  "file is required": "请选择要上传的文件",
  "invalid filename": "文件名不合法",
  "path escape rejected": "文件路径不合法",
  "check job not found": "未找到服务端检测任务",
  "streaming is not supported": "当前运行环境不支持实时事件流",
};

const codeMessages: Record<string, string> = {
  UNAUTHORIZED: "需要登录后继续操作",
  LOGIN_FAILED: "登录失败，请检查密码和验证码",
  PASSWORD_CHANGE_FAILED: "密码修改失败",
  INVALID_PAYLOAD: "提交内容格式不正确",
  DATABASE_TEST_FAILED: "数据库连接测试失败",
  DATABASE_IMPORT_FAILED: "SQLite 导入远端库失败",
  DATABASE_SYNC_FAILED: "远端库同步回本地失败",
  LEGACY_SAVE_FAILED: "兼容 JSON 保存失败",
  LEGACY_VALIDATE_FAILED: "兼容 JSON 校验失败",
  LEGACY_RESTORE_FAILED: "兼容 JSON 恢复失败",
  NOTICE_SAVE_FAILED: "版本日志保存失败",
  NOTICE_VALIDATE_FAILED: "版本日志校验失败",
  NOTICE_RESTORE_FAILED: "版本日志恢复失败",
  PACKAGE_UPLOAD_FAILED: "发布包上传失败",
  SOURCE_SAVE_FAILED: "接口源保存失败",
  CHECK_FAILED: "接口健康检测失败",
  SYNC_FAILED: "同步操作失败",
  FORBIDDEN: "没有权限执行该操作",
  METHOD_NOT_ALLOWED: "请求方法不正确",
};

export async function adminFetch<T>(target: string, init: RequestInit = {}, options: AdminApiOptions = {}): Promise<T> {
  const headers = new Headers(init.headers);
  if (!headers.has("Content-Type") && init.body && !(init.body instanceof FormData)) {
    headers.set("Content-Type", "application/json");
  }
  if (options.csrf) headers.set("X-CSRF-Token", options.csrf);
  const res = await fetch(target, { ...init, headers, credentials: "include" });
  const data = await res.json().catch(() => ({}));
  if (!res.ok || data.ok === false) {
    throw new Error(toChineseError(data.message || data.error || `HTTP ${res.status}`));
  }
  return data as T;
}

export function uploadAdminFile<T>(target: string, form: FormData, options: AdminApiOptions, onProgress: (progress: UploadProgress) => void): Promise<T> {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("POST", target);
    xhr.withCredentials = true;
    if (options.csrf) xhr.setRequestHeader("X-CSRF-Token", options.csrf);
    xhr.upload.onprogress = (event) => {
      if (event.lengthComputable) onProgress({ loaded: event.loaded, total: event.total });
    };
    xhr.onload = () => {
      const data = parseJSONSafe(xhr.responseText, {});
      if (xhr.status < 200 || xhr.status >= 300 || data.ok === false) {
        reject(new Error(toChineseError(data.message || data.error || `HTTP ${xhr.status}`)));
        return;
      }
      resolve(data as T);
    };
    xhr.onerror = () => reject(new Error("网络异常，发布包上传失败"));
    xhr.onabort = () => reject(new Error("发布包上传已取消"));
    xhr.send(form);
  });
}

export function toChineseError(value: string) {
  const raw = String(value || "").trim();
  const lower = raw.toLowerCase();
  if (exactMessages[lower]) return exactMessages[lower];
  if (codeMessages[raw]) return codeMessages[raw];
  if (/^HTTP\s+\d+/.test(raw)) return `请求失败：${raw}`;
  return raw || "操作失败";
}

function parseJSONSafe(value: string, fallback: any) {
  try {
    return JSON.parse(value || "{}");
  } catch {
    return fallback;
  }
}
