import axios, { AxiosResponse, AxiosError, InternalAxiosRequestConfig } from "axios";
import { ElLoading, ElMessage } from "element-plus";
import type { ResultDomain } from "@/types";
import { API_BASE_URL } from "@/config";

/**
 * 扩展AxiosRequestConfig以支持自定义配置
 */
interface CustomAxiosRequestConfig extends Partial<InternalAxiosRequestConfig> {
  /** 是否显示加载动画 */
  showLoading?: boolean;
  /** 是否显示错误提示 */
  showError?: boolean;
  /** 是否需要token */
  requiresAuth?: boolean;
}

/**
 * Token管理
 */
export const TokenManager = {
  /** 获取token（从localStorage获取并检查过期） */
  getToken(): string | null {
    const itemStr = localStorage.getItem('token');
    if (!itemStr) return null;
    
    try {
      const item = JSON.parse(itemStr);
      const now = Date.now();
      
      // 检查是否过期
      if (item.timestamp && item.expiresIn) {
        if (now - item.timestamp > item.expiresIn) {
          // 已过期，删除
          localStorage.removeItem('token');
          return null;
        }
      }
      
      return item.value || itemStr; // 兼容旧数据
    } catch {
      // 如果不是JSON格式，直接返回（兼容旧数据）
      return itemStr;
    }
  },
  
  /** 设置token（始终使用localStorage，根据rememberMe设置过期时间） */
  setToken(token: string, rememberMe = false): void {
    const data = {
      value: token,
      timestamp: Date.now(),
      // 如果不勾选"记住我"，设置1天过期时间；勾选则7天
      expiresIn: rememberMe ? 7 * 24 * 60 * 60 * 1000 : 1 * 24 * 60 * 60 * 1000
    };
    localStorage.setItem('token', JSON.stringify(data));
  },
  
  /** 移除token */
  removeToken(): void {
    localStorage.removeItem('token');
  },
  
  /** 检查是否有token */
  hasToken(): boolean {
    return !!this.getToken();
  }
};

/**
 * 创建axios实例
 *
 * 说明：
 * - 统一使用配置模块提供的 API_BASE_URL 作为基础路径
 * - API_BASE_URL 在开发环境来自 devConfig，在生产环境来自 window.APP_RUNTIME_CONFIG
 */
const request = axios.create({
  baseURL: API_BASE_URL,
  timeout: 30000,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
  }
});

let loadingInstance: ReturnType<typeof ElLoading.service> | null = null;

/**
 * 请求拦截器
 */
request.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const customConfig = config as CustomAxiosRequestConfig;
    
    // 默认不显示加载动画，只有 showLoading 为 true 时才展示
    if (customConfig.showLoading === true) {
      loadingInstance = ElLoading.service({
        lock: true,
        text: "加载中...",
        background: "rgba(0, 0, 0, 0.7)",
      });
    }
    
    // 添加token
    const token = TokenManager.getToken();
    if (token && config.headers) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    // 自动处理 FormData：删除 Content-Type，让浏览器自动设置（包含 boundary）
    if (config.data instanceof FormData && config.headers) {
      delete config.headers['Content-Type'];
    }
    
    return config;
  },
  (error: AxiosError) => {
    if (loadingInstance) {
      loadingInstance.close();
      loadingInstance = null;
    }
    return Promise.reject(error);
  }
);

/**
 * 响应拦截器
 */
request.interceptors.response.use(
  (response: AxiosResponse<ResultDomain<any>>) => {
    // 关闭加载动画
    if (loadingInstance) {
      loadingInstance.close();
      loadingInstance = null;
    }
    
    const result = response.data;
    
    // 检查是否为ResultDomain格式
    if (result && typeof result === 'object' && 'code' in result) {
      // 检查登录状态
      if (result.login === false) {
        ElMessage.error(result.message || '请先登录');
        TokenManager.removeToken();
        // 跳转到登录页
        window.location.href = '/login';
        return Promise.reject(new Error('未登录'));
      }
      
      // 检查权限
      if (result.auth === false) {
        ElMessage.error(result.message || '没有权限访问');
        return Promise.reject(new Error('无权限'));
      }
      
      // // 检查业务逻辑是否成功 业务逻辑不应该提前判断
      // if (!result.success) {
      //   const config = response.config as CustomAxiosRequestConfig;
      //   if (config.showError !== false) {
      //     ElMessage.error(result.message || '操作失败');
      //   }
      //   return Promise.reject(new Error(result.message || '操作失败'));
      // }
      
      // 返回成功的数据
      return response;
    }
    
    // 非ResultDomain格式，直接返回
    return response;
  },
  (error: AxiosError<ResultDomain<any>>) => {
    // 关闭加载动画
    if (loadingInstance) {
      loadingInstance.close();
      loadingInstance = null;
    }
    
    const config = error.config as CustomAxiosRequestConfig;
    
    // 处理HTTP错误
    if (error.response) {
      const { status, data } = error.response;
      
      switch (status) {
        case 401:
          ElMessage.error('认证失败，请重新登录');
          TokenManager.removeToken();
          window.location.href = '/login';
          break;
        case 403:
          ElMessage.error('没有权限访问该资源');
          break;
        case 404:
          ElMessage.error('请求的资源不存在');
          break;
        case 500:
          ElMessage.error(data?.message || '服务器内部错误');
          break;
        default:
          if (config?.showError !== false) {
            ElMessage.error(data?.message || '请求失败');
          }
      }
    } else if (error.request) {
      // 请求已发送但没有收到响应
      ElMessage.error('网络错误，请检查网络连接');
    } else {
      // 其他错误
      if (config?.showError !== false) {
        ElMessage.error(error.message || '请求失败');
      }
    }
    
    return Promise.reject(error);
  }
);

/**
 * API封装
 */
export const api = {
  /**
   * GET请求 - data参数会作为URL查询参数追加
   */
  get<T = any>(url: string, data?: any, config?: CustomAxiosRequestConfig): Promise<AxiosResponse<ResultDomain<T>>> {
    // 如果有data参数，将其转换为URL查询参数
    if (data) {
      const params = new URLSearchParams();
      Object.keys(data).forEach(key => {
        if (data[key] !== undefined && data[key] !== null) {
          params.append(key, String(data[key]));
        }
      });
      const queryString = params.toString();
      url += (url.includes('?') ? '&' : '?') + queryString;
    }
    return request.get<ResultDomain<T>>(url, config);
  },
  
  /**
   * POST请求 - data参数放到请求体
   */
  post<T = any>(url: string, data?: any, config?: CustomAxiosRequestConfig): Promise<AxiosResponse<ResultDomain<T>>> {
    return request.post<ResultDomain<T>>(url, data, config);
  },
  
  /**
   * PUT请求 - data参数放到请求体
   */
  put<T = any>(url: string, data?: any, config?: CustomAxiosRequestConfig): Promise<AxiosResponse<ResultDomain<T>>> {
    return request.put<ResultDomain<T>>(url, data, config);
  },
  
  /**
   * DELETE请求 - data参数放到请求体
   */
  delete<T = any>(url: string, data?: any, config?: CustomAxiosRequestConfig): Promise<AxiosResponse<ResultDomain<T>>> {
    return request.delete<ResultDomain<T>>(url, { ...config, data });
  },
  
  /**
   * PATCH请求 - data参数放到请求体
   */
  patch<T = any>(url: string, data?: any, config?: CustomAxiosRequestConfig): Promise<AxiosResponse<ResultDomain<T>>> {
    return request.patch<ResultDomain<T>>(url, data, config);
  },
  
  /**
   * 文件上传 (POST) - 使用 axios postForm
   */
  upload<T = any>(url: string, formData: FormData, config?: CustomAxiosRequestConfig): Promise<AxiosResponse<ResultDomain<T>>> {
    return request.postForm<ResultDomain<T>>(url, formData, config);
  },

  /**
   * 文件上传 (PUT) - 使用 axios putForm
   */
  uploadPut<T = any>(url: string, formData: FormData, config?: CustomAxiosRequestConfig): Promise<AxiosResponse<ResultDomain<T>>> {
    return request.putForm<ResultDomain<T>>(url, formData, config);
  },
  
  /**
   * 文件下载
   */
  download(url: string, filename?: string, config?: CustomAxiosRequestConfig): Promise<void> {
    return request.get(url, {
      ...config,
      responseType: 'blob'
    }).then((response) => {
      const blob = new Blob([response.data]);
      const link = document.createElement('a');
      link.href = window.URL.createObjectURL(blob);
      link.download = filename || 'download';
      link.click();
      window.URL.revokeObjectURL(link.href);
    });
  }
};

export default request;