/**axios封装
 * 请求拦截、响应拦截、统一业务错误处理
 */
import axios from "axios";
import qs from "qs";
import { ElMessage } from "element-plus";
import { TIME_OUT, BASE_URL, IS_COOKIES } from "./config";
import { useUserStore } from "@/stores/api/user";

class Request {
  constructor(timeOut, BASE_URL, IS_COOKIES) {
    this.instance = axios.create({
      timeout: timeOut,
      baseURL:
        process.env.NODE_ENV == "development"
          ? "/api/api"
          : window.location.origin + "/api",
      withCredentials: IS_COOKIES,
    });

    // 请求拦截：注入 JWT
    this.instance.interceptors.request.use((config) => {
      // 统一从 user store 读取 token，避免 key 写/读不一致
      const token = useUserStore().token;
      if (token) {
        config.headers["Authorization"] = `Bearer ${token}`;
      }
      if (config.requireToken === false) {
        // 不需要 token
      }
      if (config.jsonHeader) {
        config.headers["Content-Type"] = "application/json";
      }
      if (config.formHeader) {
        config.data = qs.stringify(config.data);
        config.headers["Content-Type"] = "application/x-www-form-urlencoded";
      }
      return config;
    });

    // 响应拦截：统一解析 ApiResponse
    this.instance.interceptors.response.use(
      (res) => res,
      (error) => {
        const status = error?.response?.status;
        // silent 模式下（如修改密码场景，401 仅代表旧密码错误），不弹通用提示、不跳登录页
        const silent = error?.config?.__silent;
        if (
          status === 401 &&
          !error?.config?.url.endsWith("/login") &&
          !error?.config?.url.endsWith("/change-password")
        ) {
          if (!silent) {
            ElMessage.error("登录已过期，请重新登录");
            useUserStore().clear();
            if (window.location.hash !== "#/login") {
              window.location.hash = "/login";
            }
          }
        } else if (status === 403) {
          if (!silent) ElMessage.error("无操作权限");
        } else if (status >= 500) {
          if (!silent) ElMessage.error("服务器内部错误");
        }else {
         ElMessage.error(error.response.data.message);
         return Promise.reject(error);
        }
      },
    );
  }

  async request(
    url,
    method,
    params,
    requireToken = true,
    headerType = "json",
    silent = false,
  ) {
    const config = {
      url,
      method,
      requireToken,
      __silent: silent,
    };
    if (headerType === "json") config.jsonHeader = true;
    if (headerType === "form") config.formHeader = true;

    if (method.toLowerCase() === "get") {
      config.params = params;
      config.paramsSerializer = function (params) {
        return qs.stringify(params, { arrayFormat: "repeat" });
      };
    } else {
      config.data = params;
    }

    return new Promise((resolve, reject) => {
      this.instance(config)
        .then((res) => {
          // 统一响应 { code, message, data }
          const body = res.data;
          if (body && typeof body === "object" && "code" in body) {
            if (body.code === 200) {
              resolve(body.data || {
                code: 200
              });
            } else if (
              body.code === 401 &&
              // 登录相关接口不弹提示（如登录页本身、修改密码页），其他接口统一处理
              !config.url.endsWith("/login") &&
              !config.url.endsWith("/change-password")
            ) {
              ElMessage.error(body.message || "未登录");
              useUserStore().clear();
              if (window.location.hash !== "#/login") {
                window.location.hash = "/login";
              }
              reject(body);
            } else {
              ElMessage.error(body.message || "请求失败");
              reject(body);
            }
          } else {
            // 非标准响应，直接返回
            resolve(body);
          }
        })
        .catch((err) => {
          reject(err);
        });
    });
  }

  // 下载二进制文件，返回 Blob
  async downloadFile(url, requireToken = true) {
    const config = {
      method: "GET",
      url,
      requireToken,
      responseType: "blob",
    };
    return new Promise((resolve, reject) => {
      this.instance(config)
        .then((res) => resolve(res.data))
        .catch((err) => reject(err));
    });
  }

  // multipart/form-data 上传；method 默认 POST，编辑接口需要 PUT 时可传入
  async uploadFile(url, formData, requireToken = true, method = "POST") {
    const config = {
      method,
      url,
      data: formData,
      requireToken,
      headers: { "Content-Type": "multipart/form-data" },
    };
    return new Promise((resolve, reject) => {
      this.instance(config)
        .then((res) => {
          const body = res.data;
          if (body && typeof body === "object" && "code" in body) {
            if (body.code === 200) resolve(body.data);
            else {
              ElMessage.error(body.message || "上传失败");
              reject(body);
            }
          } else {
            resolve(body);
          }
        })
        .catch((err) => reject(err));
    });
  }
}

export default new Request(TIME_OUT, BASE_URL, IS_COOKIES);
