const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const crypto = require('crypto');
const prisma = require('./prisma');

const JWT_EXPIRES_IN = '7d';
const ADMIN_JWT_EXPIRES_IN = '7d';

// 安全：生产环境必须配置 JWT_SECRET，杜绝硬编码密钥
const JWT_SECRET = process.env.JWT_SECRET;
if (!JWT_SECRET) {
  if (process.env.NODE_ENV === 'production') {
    throw new Error(
      'JWT_SECRET 环境变量未设置。请在 .env 文件中配置一个随机密钥（可用 `openssl rand -hex 32` 生成）。'
    );
  }
  console.warn('[安全警告] JWT_SECRET 未设置，使用开发环境临时密钥。请勿在生产环境使用。');
}
const SECRET = JWT_SECRET || 'dev_only_insecure_secret_do_not_use_in_production';

// Admin JWT 使用独立 secret，防止跨角色伪造
// 生产环境必须配置 ADMIN_JWT_SECRET，否则 fail-fast
const ADMIN_JWT_SECRET = process.env.ADMIN_JWT_SECRET;
if (!ADMIN_JWT_SECRET) {
  if (process.env.NODE_ENV === 'production') {
    throw new Error(
      'ADMIN_JWT_SECRET 环境变量未设置。请在 .env 文件中配置一个独立于 JWT_SECRET 的随机密钥（可用 `openssl rand -hex 32` 生成）。'
    );
  }
  console.warn('[安全警告] ADMIN_JWT_SECRET 未设置，使用开发环境临时密钥。请勿在生产环境使用。');
}
const ADMIN_SECRET = ADMIN_JWT_SECRET || 'dev_only_admin_insecure_secret';

// 哈希密码
function hashPassword(password) {
  return bcrypt.hashSync(password, 10);
}

// 验证密码
function verifyPassword(password, hash) {
  return bcrypt.compareSync(password, hash);
}

// 生成 JWT
function signToken(userId) {
  return jwt.sign({ userId }, SECRET, { expiresIn: JWT_EXPIRES_IN });
}

// 验证 JWT 并提取 userId
function verifyToken(token) {
  try {
    const decoded = jwt.verify(token, SECRET);
    return decoded.userId;
  } catch {
    return null;
  }
}

// Express 中间件：验证 JWT
function authMiddleware(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: '未登录' });
  }
  const token = authHeader.slice(7);
  const userId = verifyToken(token);
  if (!userId) {
    return res.status(401).json({ error: '登录已过期，请重新登录' });
  }
  req.userId = userId;
  next();
}

// Express 中间件：验证 API Key（用于 Hermes 配置拉取）
// 支持 JWT token 和 API Key（eak_ 前缀）两种认证方式
async function apiKeyMiddleware(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: '需要认证' });
  }
  const token = authHeader.slice(7);

  // 如果是 API Key（eak_ 前缀），查数据库验证
  if (token.startsWith('eak_')) {
    try {
      const keyHash = crypto.createHash('sha256').update(token).digest('hex');
      const apiKey = await prisma.apiKey.findUnique({
        where: { keyHash },
        select: { id: true, userId: true },
      });
      if (!apiKey) {
        return res.status(401).json({ error: 'API Key 无效' });
      }
      // 更新最后使用时间（不阻塞请求）
      prisma.apiKey.update({
        where: { id: apiKey.id },
        data: { lastUsedAt: new Date() },
      }).catch((err) => console.warn('更新 API Key lastUsedAt 失败:', err));
      req.userId = apiKey.userId;
      req.authMethod = 'apikey';
      return next();
    } catch (err) {
      console.error('API Key 验证失败:', err);
      return res.status(500).json({ error: '认证失败' });
    }
  }

  // 否则尝试 JWT 认证
  const userId = verifyToken(token);
  if (!userId) {
    return res.status(401).json({ error: '认证无效' });
  }
  req.userId = userId;
  req.authMethod = 'jwt';
  next();
}

// ===== Admin 认证 =====

// 生成 Admin JWT
function adminSignToken(adminId) {
  return jwt.sign({ adminId, role: 'admin' }, ADMIN_SECRET, { expiresIn: ADMIN_JWT_EXPIRES_IN });
}

// 验证 Admin JWT
function adminVerifyToken(token) {
  try {
    const decoded = jwt.verify(token, ADMIN_SECRET);
    if (decoded.role !== 'admin') return null;
    return decoded.adminId;
  } catch {
    return null;
  }
}

// Express 中间件：验证 Admin JWT
function adminAuthMiddleware(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: '管理员未登录' });
  }
  const token = authHeader.slice(7);
  const adminId = adminVerifyToken(token);
  if (!adminId) {
    return res.status(401).json({ error: '管理员登录已过期，请重新登录' });
  }
  req.adminId = adminId;
  next();
}

module.exports = {
  hashPassword,
  verifyPassword,
  signToken,
  verifyToken,
  authMiddleware,
  apiKeyMiddleware,
  adminSignToken,
  adminVerifyToken,
  adminAuthMiddleware,
};
