/**
 * API认证问题的解决指南
 * 本文件提供了解决API认证问题的常见方法和实现示例
 */

/**
 * 一、常见的API认证机制
 * 
 * 1. HTTP Basic Authentication（基本认证）
 * - 最简单的认证方式，将用户名和密码用Base64编码后放在请求头中
 * - 优点：实现简单
 * - 缺点：安全性较低，凭证容易被截获和解码
 * - 使用场景：内部系统或测试环境
 * 
 * 2. Bearer Token（令牌认证）
 * - 服务器颁发一个令牌（通常是JWT格式），客户端在请求头中携带此令牌
 * - 优点：安全性较高，可以设置过期时间和权限范围
 * - 使用场景：大多数现代API
 * 
 * 3. OAuth 2.0
 * - 授权框架，允许第三方应用在用户授权的情况下访问资源
 * - 包含多种授权流程：授权码、隐式授权、客户端凭证、密码凭证等
 * - 优点：安全性高，支持复杂的授权场景
 * - 使用场景：需要第三方应用访问用户数据的场景
 * 
 * 4. API Key认证
 * - 客户端使用预先分配的API Key来标识自己
 * - 优点：实现简单，易于追踪使用情况
 * - 缺点：API Key如果泄露可能导致安全问题
 * - 使用场景：公开API或内部系统
 */

/**
 * 二、Bearer Token认证的实现示例
 * 
 * 在实际项目中，Bearer Token是最常用的认证方式之一。
 * 以下是一个完整的实现流程：
 */

/**
 * 获取认证令牌
 * @param {string} username - 用户名
 * @param {string} password - 密码
 * @returns {Promise<string>} 认证令牌
 */
export async function getAuthToken(username, password) {
  try {
    const response = await fetch('https://ad.ningmuyun.com/bank/api/auth/login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        username,
        password
      })
    });
    
    if (!response.ok) {
      throw new Error(`登录失败: ${response.status} ${response.statusText}`);
    }
    
    const data = await response.json();
    // 假设API返回的令牌字段为token
    return data.token;
  } catch (error) {
    console.error('获取认证令牌失败:', error);
    throw error;
  }
}

/**
 * 使用Bearer Token调用API
 * @param {string} url - API地址
 * @param {string} token - 认证令牌
 * @param {Object} options - fetch选项
 * @returns {Promise<any>} API响应数据
 */
export async function fetchWithAuth(url, token, options = {}) {
  try {
    const response = await fetch(url, {
      ...options,
      headers: {
        ...options.headers,
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      credentials: 'include' // 包含Cookie（如果需要）
    });
    
    if (!response.ok) {
      if (response.status === 401) {
        throw new Error('认证失败，请重新登录');
      }
      throw new Error(`API请求失败: ${response.status} ${response.statusText}`);
    }
    
    return await response.json();
  } catch (error) {
    console.error('带认证的API请求失败:', error);
    throw error;
  }
}

/**
 * 三、CORS跨域问题的处理方案
 * 
 * 当API请求遇到CORS（跨域资源共享）问题时，可以采取以下解决方案：
 */

/**
 * 1. 服务器端设置CORS头
 * 服务器需要在响应中添加以下头信息：
 * - Access-Control-Allow-Origin: 指定允许的源（域名）
 * - Access-Control-Allow-Methods: 指定允许的HTTP方法
 * - Access-Control-Allow-Headers: 指定允许的请求头
 * - Access-Control-Allow-Credentials: 是否允许携带凭证（如Cookie）
 * 
 * 2. 使用代理服务器
 * - 在开发环境中，可以配置Vite、Webpack等构建工具的代理
 * - 在生产环境中，可以使用Nginx、Apache等服务器设置反向代理
 * 
 * 3. 处理预检请求（OPTIONS请求）
 * - 对于复杂请求，浏览器会先发送OPTIONS请求检查服务器是否允许跨域
 * - 服务器需要正确响应OPTIONS请求
 */

/**
 * Vite开发服务器代理配置示例
 * 在vite.config.js中添加以下配置：
 * 
 * export default defineConfig({
 *   server: {
 *     proxy: {
 *       '/api': {
 *         target: 'https://ad.ningmuyun.com',
 *         changeOrigin: true,
 *         rewrite: (path) => path.replace(/^\/api/, '')
 *       }
 *     }
 *   }
 * })
 * 
 * 然后将API调用改为相对路径：
 * fetch('/api/bank/api/projects?page=1&limit=12&search=&status=')
 */

/**
 * 四、实际项目中的最佳实践
 */

export const apiAuthBestPractices = {
  // 1. 安全存储认证信息
  secureStorage: [
    '不要将令牌存储在本地存储（localStorage）中，容易受到XSS攻击',
    '使用HttpOnly Cookie存储令牌，防止JavaScript访问',
    '或者使用内存存储，并在页面刷新时重新获取令牌'
  ],
  
  // 2. 令牌管理
  tokenManagement: [
    '实现令牌过期自动刷新机制',
    '设置合理的令牌过期时间',
    '定期清理过期令牌'
  ],
  
  // 3. 请求处理
  requestHandling: [
    '为所有API请求添加超时处理',
    '实现请求重试机制',
    '添加请求进度显示'
  ],
  
  // 4. 错误处理
  errorHandling: [
    '统一处理认证错误（如401状态码）',
    '为用户提供清晰的错误提示',
    '记录详细的错误日志以便排查'
  ]
};

/**
 * 五、临时解决方案（当无法修改服务器配置时）
 * 
 * 如果API提供者无法或不愿意修改CORS和认证配置，可以采取以下临时解决方案：
 */

export const temporarySolutions = {
  // 1. 使用模拟数据
  mockData: '创建与API返回格式一致的模拟数据，用于开发和测试',
  
  // 2. 使用公共代理服务
  publicProxy: '使用如cors-anywhere、https://api.allorigins.win等公共代理服务',
  
  // 3. 浏览器插件
  browserExtensions: '开发环境下可以使用Allow CORS等浏览器插件临时解决跨域问题',
  
  // 4. 本地代理服务器
  localProxy: '在本地启动一个简单的Node.js服务器作为代理，转发API请求'
};

/**
 * 六、完整的认证流程示例
 * 
 * 以下是一个在Vue应用中使用的完整认证流程示例：
 */

/**
 * Vue应用中的认证服务示例
 */
export class AuthService {
  constructor() {
    this.token = null;
    this.tokenKey = 'auth_token';
  }
  
  // 初始化认证服务
  init() {
    // 尝试从安全存储中恢复令牌
    const storedToken = this.getStoredToken();
    if (storedToken) {
      this.token = storedToken;
    }
  }
  
  // 获取存储的令牌（这里简化处理，实际应使用更安全的存储方式）
  getStoredToken() {
    try {
      return sessionStorage.getItem(this.tokenKey);
    } catch (error) {
      console.error('获取存储的令牌失败:', error);
      return null;
    }
  }
  
  // 存储令牌
  storeToken(token) {
    try {
      sessionStorage.setItem(this.tokenKey, token);
      this.token = token;
    } catch (error) {
      console.error('存储令牌失败:', error);
    }
  }
  
  // 清除令牌
  clearToken() {
    sessionStorage.removeItem(this.tokenKey);
    this.token = null;
  }
  
  // 检查是否已认证
  isAuthenticated() {
    return !!this.token;
  }
  
  // 登录
  async login(username, password) {
    try {
      const token = await getAuthToken(username, password);
      this.storeToken(token);
      return true;
    } catch (error) {
      console.error('登录失败:', error);
      throw error;
    }
  }
  
  // 登出
  logout() {
    this.clearToken();
  }
  
  // 带认证的API请求
  async request(url, options = {}) {
    if (!this.token) {
      throw new Error('未认证，请先登录');
    }
    
    try {
      return await fetchWithAuth(url, this.token, options);
    } catch (error) {
      // 处理认证失败
      if (error.message.includes('认证失败')) {
        this.clearToken();
        // 可以在这里触发重新登录流程
        throw new Error('认证已过期，请重新登录');
      }
      throw error;
    }
  }
}