import axios, { type AxiosInstance, type AxiosResponse, type InternalAxiosRequestConfig as _InternalAxiosRequestConfig } from 'axios';
import { isObject } from '@/utils/verify';
import { responseRefreshTokenFun } from './response-refresh-token';
import { type ResuestRefreshToken, requestRefreshTokenFun } from './request-refresh-token';
import { type ReqRefreshToken, logoutUrl, tokenUrlWhiteList } from '@/api/login';
import type { UserStore } from '@/pinia/modules/user';
import { invoke } from '@tauri-apps/api/core';
import { getDefaultAuthHeaders } from './auth-headers';

interface InternalAxiosRequestConfig<T> extends _InternalAxiosRequestConfig<T> {
  errData?: { data?: any; msg: string; code: number };
}

export type Response<T = unknown> = {
  code: number;
  msg: string | null;
  data: T;
};
/** 分页 */
export type Paging<T> = {
  /** 数据 */
  list: T[];
  /** 总条数  */
  total: number;
};

const instance: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_BASE_URL,
});

/** 通用请求头 */
instance.defaults.headers.common['Content-Type'] = 'application/json';

/** POST 方法请求头 */
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

/** 超时时间 */
instance.defaults.timeout = 30000;

/** 默认请求方式 */
instance.defaults.method = 'POST';

/** 校验状态码 */
instance.defaults.validateStatus = (status) => {
  return status === 200;
};

/** 请求前拦截 */
instance.interceptors.request.use(
  async (config: InternalAxiosRequestConfig<any>): Promise<InternalAxiosRequestConfig<any>> => {
    try {
      config.headers = config.headers || {};
      const userStore: UserStore = useUserStore();
      const defAuthHeaders = getDefaultAuthHeaders();

      config.headers['Custom-Mac'] = config.headers['Custom-Mac'] ?? defAuthHeaders['Custom-Mac'];
      config.headers['Custom-Platform'] = config.headers['Custom-Platform'] ?? defAuthHeaders['Custom-Platform'];
      config.headers['Custom-Timestamp'] = config.headers['Custom-Timestamp'] ?? defAuthHeaders['Custom-Timestamp'];

      // 当有token时才调用
      if (userStore.userInfo?.token) {
        config.headers.Authorization = config.headers.Authorization ?? defAuthHeaders.Authorization;
        if (userStore.userInfo) {
          // 排除 refreshTokenUrl 接口
          if (tokenUrlWhiteList.includes(config.url || '')) {
            return Promise.resolve(config);
          }

          const currentTime = Math.floor(Date.now() / 1000); // 当前时间（秒）
          const access_token_expired = userStore.userInfo.tokenExpired + userStore.userInfo.tokenTimestamp;

          const refresh_token = userStore.userInfo.refreshToken || '';
          const refresh_token_expired = userStore.userInfo.refreshTokenExpired + userStore.userInfo.tokenTimestamp;

          // 如果 token 存在且即将过期（小于 60 秒），刷新 token
          if (access_token_expired - currentTime <= 60 && refresh_token && refresh_token_expired > currentTime) {
            try {
              const res: ResuestRefreshToken = await requestRefreshTokenFun(config, refresh_token);
              res.config.headers.Authorization = `Bearer ${res.data!.token}`;
              await updateToken(userStore, res.data!);
              return res.config;
              // oxlint-disable-next-line no-unused-vars
            } catch (error: any) {
              config.errData = { msg: '刷新token失败,BD214', code: -10002 };
              config.url !== logoutUrl && userStore.logout();
              return Promise.reject(config);
            }
          } else if (refresh_token_expired < currentTime) {
            config.errData = { msg: '刷新token失败,BD213', code: -10002 };
            config.url !== logoutUrl && (await userStore.logout());
            return Promise.reject(config);
          }
        }
      }
      return Promise.resolve(config);
      // oxlint-disable-next-line no-unused-vars
    } catch (e) {
      config.errData = { msg: '请求异常,BD215', code: -10002 };
      return Promise.reject(config);
    }
  },
  (config) => {
    const _config = isObject(config) ? config : {};
    _config.errData = { msg: '请求异常,BD215', code: -10002 };
    return Promise.reject(_config);
  }
);

/** 请求后拦截 */
instance.interceptors.response.use(
  async (response): Promise<any> => {
    try {
      const userStore: UserStore = useUserStore();
      if (response.data && isObject(response.data)) {
        try {
          if ('code' in response.data && response.data.code === 200) {
            return Promise.resolve(response.data);
          } else if ('code' in response.data && response.data.code === 401) {
            const currentTime = Math.floor(Date.now() / 1000); // 当前时间（秒）
            const refresh_token_expired = userStore.userInfo!.refreshTokenExpired + userStore.userInfo!.tokenTimestamp;
            if (
              !userStore.userInfo ||
              tokenUrlWhiteList.includes(response.config.url || '') ||
              !userStore.userInfo?.token ||
              refresh_token_expired < currentTime
            ) {
              response.config.url !== logoutUrl && userStore.logout();
              return Promise.reject(requestComFail(response));
            }
            if (!tokenUrlWhiteList.includes(response.config.url || '')) {
              try {
                const res = await responseRefreshTokenFun(userStore.userInfo?.refreshToken || '');
                response.config.headers.Authorization = `Bearer ${res.data.token}`;
                await updateToken(userStore, res.data);
                return instance.request(response.config);
                // oxlint-disable-next-line no-unused-vars
              } catch (error: any) {
                response.config.url !== logoutUrl && userStore.logout();
                return Promise.reject(requestComFail(response));
              }
            }
            return Promise.reject(requestComFail(response));
          } else if ('code' in response.data && (response.data.code === 400 || response.data.code === 403 || response.data.code === 409)) {
            response.config.url !== logoutUrl && userStore.logout();
            return Promise.reject(requestComFail(response));
          } else {
            response.data = { code: response.data?.code ?? -20001, msg: response.data?.msg ?? '代码错误，BD2001' };
            return Promise.reject(requestComFail(response));
          }
          // oxlint-disable-next-line no-unused-vars
        } catch (e) {
          response.data = { code: response.data?.code ?? -20002, msg: response.data?.msg || '请求失败，BD2002' };
          return Promise.reject(requestComFail(response));
        }
      } else {
        response.data = { code: -20003, msg: '数据格式错误，BD2003' };
        return Promise.reject({ code: -1003, msg: '请求失败，数据格式错误' });
      }
    } catch (e) {
      console.error('代码错误1：', e);
      response.data = { code: -20004, msg: '代码错误，BD004' };
      return Promise.reject(requestComFail(response));
    }
  },
  (response) => {
    if (response && isObject(response)) {
      if (isObject(response.errData) && response.errData && 'code' in response.errData && 'msg' in response.errData) {
        return Promise.reject(requestComFail({ data: response.errData } as AxiosResponse));
      } else if ('code' in response && 'msg' in response) {
        return Promise.reject(requestComFail({ data: response } as AxiosResponse));
      }
    }
    const _response = isObject(response) ? response : ({ data: {} } as AxiosResponse);
    _response.data = { code: -20006, msg: '请求失败，请确认地址是否正确，BD006' };
    return Promise.reject(requestComFail(_response as AxiosResponse));
  }
);

/** 请求结果 */
function requestComFail(response: AxiosResponse): Response {
  const data = isObject(response.data) ? response.data : {};
  const status = 'status' in response ? response.status : -1;
  if ('code' in data && 'msg' in data) {
    return data as Response;
  }
  if (status !== 200) {
    if (!('code' in data) || !('msg' in data)) {
      data.code = -1000;
      data.msg = '请求失败，-1000';
    }
  }
  if (status === 404) {
    data.code = status;
    data.msg = '链接已失效，404';
  } else if (status === 500) {
    data.code = status;
    data.msg = '服务器内部错误，500';
  }
  const ersResult = { ...data, data: data.data || null } as Response;
  return ersResult;
}

/**
 * 更新token
 */
async function updateToken(userStore: UserStore, reqRefreshToken: ReqRefreshToken) {
  await userStore.setUserInfo({ ...(userStore.userInfo! || {}), ...(reqRefreshToken || {}) });
  // 同步保存到 Rust session_storage
  try {
    if (reqRefreshToken.token) {
      await invoke('session_storage_set', { key: 'access_token', value: reqRefreshToken.token });
    }
    if (reqRefreshToken.refreshToken) {
      await invoke('session_storage_set', { key: 'refresh_token', value: reqRefreshToken.refreshToken });
    }
  } catch (e) {
    console.error('同步 Token 到 Rust 失败:', e);
  }
  await nextTick();
}

export default instance;
