const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const { UserDB, DeviceSessionDB } = require('./database');
const { decryptSecret } = require('./utils/encryption');
const DEFAULT_LOCAL_STORAGE_QUOTA_BYTES = 1024 * 1024 * 1024; // 1GB
const DEFAULT_OSS_STORAGE_QUOTA_BYTES = 1024 * 1024 * 1024; // 1GB

// JWT密钥（必须在环境变量中设置）
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
// Refresh Token密钥（使用不同的密钥）
const REFRESH_SECRET = process.env.REFRESH_SECRET || JWT_SECRET + '-refresh';

// Token有效期配置
const ACCESS_TOKEN_EXPIRES = '2h';    // Access token 2小时
const REFRESH_TOKEN_EXPIRES = '7d';   // Refresh token 7天

// 安全检查：验证JWT密钥配置
const DEFAULT_SECRETS = [
  'your-secret-key-change-in-production',
  'your-secret-key-change-in-production-PLEASE-CHANGE-THIS'
];

// 安全修复：增强 JWT_SECRET 验证逻辑
if (DEFAULT_SECRETS.includes(JWT_SECRET)) {
  const errorMsg = `
╔═══════════════════════════════════════════════════════════════╗
║                    ⚠️  安全警告  ⚠️                            ║
╠═══════════════════════════════════════════════════════════════╣
║  JWT_SECRET 使用默认值，存在严重安全风险！                    ║
║                                                               ║
║  请立即设置环境变量 JWT_SECRET                                ║
║  生成随机密钥:                                                ║
║  node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
║                                                               ║
║  在 backend/.env 文件中设置:                                  ║
║  JWT_SECRET=你生成的随机密钥                                  ║
╚═══════════════════════════════════════════════════════════════╝
  `;

  // 安全修复：无论环境如何，使用默认 JWT_SECRET 都拒绝启动
  console.error(errorMsg);
  throw new Error('使用默认 JWT_SECRET 存在严重安全风险，服务无法启动！');
}

// 验证 JWT_SECRET 长度（至少 32 字节/64个十六进制字符）
if (JWT_SECRET.length < 32) {
  const errorMsg = `
╔═══════════════════════════════════════════════════════════════╗
║                    ⚠️  配置错误  ⚠️                            ║
╠═══════════════════════════════════════════════════════════════╣
║  JWT_SECRET 长度不足！                                        ║
║                                                               ║
║  要求: 至少 32 字节                                           ║
║  当前长度: ${JWT_SECRET.length} 字节                           ║
║                                                               ║
║  生成安全的随机密钥:                                          ║
║  node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
╚═══════════════════════════════════════════════════════════════╝
  `;
  console.error(errorMsg);
  throw new Error('JWT_SECRET 长度不足，服务无法启动！');
}

console.log('[安全] ✓ JWT密钥验证通过');

// 生成Access Token（短期）
function generateToken(user, sessionId = null) {
  const safeSessionId = typeof sessionId === 'string' && sessionId.trim() ? sessionId.trim() : null;
  return jwt.sign(
    {
      id: user.id,
      username: user.username,
      is_admin: user.is_admin,
      type: 'access',
      sid: safeSessionId,
      jti: crypto.randomBytes(12).toString('hex')
    },
    JWT_SECRET,
    { expiresIn: ACCESS_TOKEN_EXPIRES }
  );
}

// 生成Refresh Token（长期）
function generateRefreshToken(user, sessionId = null) {
  const safeSessionId = typeof sessionId === 'string' && sessionId.trim() ? sessionId.trim() : null;
  return jwt.sign(
    {
      id: user.id,
      type: 'refresh',
      sid: safeSessionId,
      // 添加随机标识，使每次生成的refresh token不同
      jti: crypto.randomBytes(16).toString('hex')
    },
    REFRESH_SECRET,
    { expiresIn: REFRESH_TOKEN_EXPIRES }
  );
}

function decodeAccessToken(token) {
  if (!token || typeof token !== 'string') return null;
  try {
    return jwt.verify(token, JWT_SECRET);
  } catch {
    return null;
  }
}

function decodeRefreshToken(token) {
  if (!token || typeof token !== 'string') return null;
  try {
    return jwt.verify(token, REFRESH_SECRET);
  } catch {
    return null;
  }
}

// 验证Refresh Token并返回新的Access Token
function refreshAccessToken(refreshToken, context = {}) {
  try {
    const decoded = jwt.verify(refreshToken, REFRESH_SECRET);

    if (decoded.type !== 'refresh') {
      return { success: false, message: '无效的刷新令牌类型' };
    }

    const sessionId = typeof decoded.sid === 'string' ? decoded.sid.trim() : '';
    if (sessionId) {
      const activeSession = DeviceSessionDB.findActiveBySessionId(sessionId);
      if (!activeSession || Number(activeSession.user_id) !== Number(decoded.id)) {
        return { success: false, message: '当前设备会话已失效，请重新登录' };
      }
      DeviceSessionDB.touch(sessionId, {
        ipAddress: context.ipAddress,
        userAgent: context.userAgent
      });
    }

    const user = UserDB.findById(decoded.id);

    if (!user) {
      return { success: false, message: '用户不存在' };
    }

    if (user.is_banned) {
      return { success: false, message: '账号已被封禁' };
    }

    if (!user.is_active) {
      return { success: false, message: '账号未激活' };
    }

    // 生成新的access token
    const newAccessToken = generateToken(user, sessionId || null);

    return {
      success: true,
      token: newAccessToken,
      sessionId: sessionId || null,
      user: {
        id: user.id,
        username: user.username,
        is_admin: user.is_admin
      }
    };
  } catch (error) {
    if (error.name === 'TokenExpiredError') {
      return { success: false, message: '刷新令牌已过期，请重新登录' };
    }
    return { success: false, message: '无效的刷新令牌' };
  }
}

// 验证Token中间件
function authMiddleware(req, res, next) {
  // 从请求头或HttpOnly Cookie获取token（不再接受URL参数以避免泄露）
  const token = req.headers.authorization?.replace('Bearer ', '') || req.cookies?.token;

  if (!token) {
    return res.status(401).json({
      success: false,
      message: '未提供认证令牌'
    });
  }

  try {
    const decoded = jwt.verify(token, JWT_SECRET);

    if (decoded.type !== 'access') {
      return res.status(401).json({
        success: false,
        message: '无效的令牌类型'
      });
    }

    const sessionId = typeof decoded.sid === 'string' ? decoded.sid.trim() : '';
    if (sessionId) {
      const activeSession = DeviceSessionDB.findActiveBySessionId(sessionId);
      if (!activeSession || Number(activeSession.user_id) !== Number(decoded.id)) {
        return res.status(401).json({
          success: false,
          message: '当前设备已下线，请重新登录'
        });
      }
      DeviceSessionDB.touch(sessionId, {
        ipAddress: req.ip || req.socket?.remoteAddress || '',
        userAgent: req.get('user-agent') || ''
      });
    }

    const user = UserDB.findById(decoded.id);

    if (!user) {
      return res.status(401).json({
        success: false,
        message: '用户不存在'
      });
    }

    if (user.is_banned) {
      return res.status(403).json({
        success: false,
        message: '账号已被封禁'
      });
    }

    if (!user.is_active) {
      return res.status(403).json({
        success: false,
        message: '账号未激活'
      });
    }

    const rawOssQuota = Number(user.oss_storage_quota);
    const effectiveOssQuota = Number.isFinite(rawOssQuota) && rawOssQuota > 0
      ? rawOssQuota
      : DEFAULT_OSS_STORAGE_QUOTA_BYTES;
    const rawDownloadTrafficQuota = Number(user.download_traffic_quota);
    const effectiveDownloadTrafficQuota = Number.isFinite(rawDownloadTrafficQuota) && rawDownloadTrafficQuota > 0
      ? Math.floor(rawDownloadTrafficQuota)
      : 0; // 0 表示不限流量
    const rawDownloadTrafficUsed = Number(user.download_traffic_used);
    const normalizedDownloadTrafficUsed = Number.isFinite(rawDownloadTrafficUsed) && rawDownloadTrafficUsed > 0
      ? Math.floor(rawDownloadTrafficUsed)
      : 0;
    const cappedDownloadTrafficUsed = effectiveDownloadTrafficQuota > 0
      ? Math.min(normalizedDownloadTrafficUsed, effectiveDownloadTrafficQuota)
      : normalizedDownloadTrafficUsed;

    // 将用户信息附加到请求对象（包含所有存储相关字段）
    req.user = {
      id: user.id,
      username: user.username,
      email: user.email,
      is_admin: user.is_admin,
      // OSS存储字段（v3.0新增）
      has_oss_config: user.has_oss_config || 0,
      oss_provider: user.oss_provider,
      oss_region: user.oss_region,
      oss_access_key_id: user.oss_access_key_id,
      // 安全修复：解密 OSS Access Key Secret（如果存在）
      oss_access_key_secret: user.oss_access_key_secret ? decryptSecret(user.oss_access_key_secret) : null,
      oss_bucket: user.oss_bucket,
      oss_endpoint: user.oss_endpoint,
      // 存储相关字段
      storage_permission: user.storage_permission || 'oss_only',
      current_storage_type: user.current_storage_type || 'oss',
      local_storage_quota: user.local_storage_quota || DEFAULT_LOCAL_STORAGE_QUOTA_BYTES,
      local_storage_used: user.local_storage_used || 0,
      oss_storage_quota: effectiveOssQuota,
      storage_used: user.storage_used || 0,
      download_traffic_quota: effectiveDownloadTrafficQuota,
      download_traffic_used: cappedDownloadTrafficUsed,
      download_traffic_quota_expires_at: user.download_traffic_quota_expires_at || null,
      download_traffic_reset_cycle: user.download_traffic_reset_cycle || 'none',
      download_traffic_last_reset_at: user.download_traffic_last_reset_at || null,
      // 主题偏好
      theme_preference: user.theme_preference || null
    };
    req.authSessionId = sessionId || null;
    req.authTokenJti = typeof decoded.jti === 'string' ? decoded.jti : null;

    next();
  } catch (error) {
    if (error.name === 'TokenExpiredError') {
      return res.status(401).json({
        success: false,
        message: '令牌已过期'
      });
    }

    return res.status(401).json({
      success: false,
      message: '无效的令牌'
    });
  }
}

// 管理员权限中间件
function adminMiddleware(req, res, next) {
  if (!req.user || !req.user.is_admin) {
    return res.status(403).json({
      success: false,
      message: '需要管理员权限'
    });
  }
  next();
}

/**
 * 管理员敏感操作二次验证中间件
 *
 * 要求管理员重新输入密码才能执行敏感操作
 * 防止会话劫持后的非法操作
 *
 * @example
 * app.delete('/api/admin/users/:id',
 *   authMiddleware,
 *   adminMiddleware,
 *   requirePasswordConfirmation,
 *   async (req, res) => { ... }
 * );
 */
function requirePasswordConfirmation(req, res, next) {
  const { password } = req.body;

  // 检查是否提供了密码
  if (!password) {
    return res.status(400).json({
      success: false,
      message: '执行此操作需要验证密码',
      require_password: true
    });
  }

  // 验证密码长度（防止空密码）
  if (password.length < 6) {
    return res.status(400).json({
      success: false,
      message: '密码格式错误'
    });
  }

  // 从数据库重新获取用户信息（不依赖 req.user 中的数据）
  const user = UserDB.findById(req.user.id);

  if (!user) {
    return res.status(404).json({
      success: false,
      message: '用户不存在'
    });
  }

  // 验证密码
  const isPasswordValid = UserDB.verifyPassword(password, user.password);

  if (!isPasswordValid) {
    // 记录安全日志：密码验证失败
    SystemLogDB = require('./database').SystemLogDB;
    SystemLogDB.log({
      level: SystemLogDB.LEVELS.WARN,
      category: SystemLogDB.CATEGORIES.SECURITY,
      action: 'admin_password_verification_failed',
      message: '管理员敏感操作密码验证失败',
      userId: req.user.id,
      username: req.user.username,
      ipAddress: req.ip,
      userAgent: req.get('user-agent'),
      details: {
        endpoint: req.path,
        method: req.method
      }
    });

    return res.status(403).json({
      success: false,
      message: '密码验证失败，操作已拒绝'
    });
  }

  // 密码验证成功，继续执行
  next();
}

// 检查JWT密钥是否安全
function isJwtSecretSecure() {
  return !DEFAULT_SECRETS.includes(JWT_SECRET) && JWT_SECRET.length >= 32;
}

module.exports = {
  JWT_SECRET,
  generateToken,
  generateRefreshToken,
  decodeAccessToken,
  decodeRefreshToken,
  refreshAccessToken,
  authMiddleware,
  adminMiddleware,
  requirePasswordConfirmation, // 导出二次验证中间件
  isJwtSecretSecure,
  ACCESS_TOKEN_EXPIRES,
  REFRESH_TOKEN_EXPIRES
};
