const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const crypto = require('crypto');
const UserMySQL = require('../models/UserMySQL');
const { AppError } = require('../utils/errors');
const { success } = require('../utils/response');
const { sendEmail } = require('../utils/email');

// 生成JWT Token
const generateToken = (userId) => {
  return jwt.sign(
    { userId },
    process.env.JWT_SECRET || 'your-secret-key',
    { expiresIn: process.env.JWT_EXPIRE || '7d' }
  );
};

// 生成刷新Token
const generateRefreshToken = (userId) => {
  return jwt.sign(
    { userId, type: 'refresh' },
    process.env.JWT_REFRESH_SECRET || 'your-refresh-secret-key',
    { expiresIn: process.env.JWT_REFRESH_EXPIRE || '30d' }
  );
};

// 生成验证码
const generateVerificationCode = () => {
  return crypto.randomBytes(32).toString('hex');
};

// 用户注册
const register = async (req, res, next) => {
  try {
    const { username, password, nickname, email, phone } = req.body;

    // 检查用户名是否已存在
    if (await UserMySQL.isUsernameExists(username)) {
      throw new AppError('用户名已存在', 400);
    }

    // 检查邮箱是否已存在
    if (email && await UserMySQL.isEmailExists(email)) {
      throw new AppError('邮箱已存在', 400);
    }

    // 检查手机号是否已存在
    if (phone && await UserMySQL.isPhoneExists(phone)) {
      throw new AppError('手机号已存在', 400);
    }

    // 加密密码
    const hashedPassword = await bcrypt.hash(password, 12);

    // 创建新用户
    const userId = await UserMySQL.create({
      username,
      password_hash: hashedPassword,
      user_type: 'farmer',
      real_name: nickname || username,
      avatar_url: '',
      email,
      phone
    });

    // 获取用户信息
    const user = await UserMySQL.findById(userId);
    
    // 生成token和刷新token
    const token = generateToken(userId);
    const refreshToken = generateRefreshToken(userId);

    // 更新最后登录时间
    await UserMySQL.updateLastLogin(userId);

    res.status(201).json(success({
      user: UserMySQL.sanitize(user),
      token,
      refreshToken,
      message: '注册成功'
    }));
  } catch (error) {
    next(error);
  }
};

// 用户登录
const login = async (req, res, next) => {
  try {
    const { username, password } = req.body;

    if (!username || !password) {
      throw new AppError('用户名和密码不能为空', 400);
    }

    // 查找用户（支持用户名、邮箱、手机号登录）
    let user = await UserMySQL.findByUsername(username);
    if (!user) {
      user = await UserMySQL.findByEmail(username);
    }
    if (!user) {
      user = await UserMySQL.findByPhone(username);
    }

    if (!user) {
      throw new AppError('用户不存在', 404);
    }

    // 检查用户状态
    if (!UserMySQL.isActive(user)) {
      throw new AppError('账户已被禁用', 403);
    }

    // 验证密码
    const isPasswordValid = await bcrypt.compare(password, user.password_hash);
    if (!isPasswordValid) {
      throw new AppError('密码错误', 401);
    }

    // 生成token和刷新token
    const token = generateToken(user.id);
    const refreshToken = generateRefreshToken(user.id);

    // 更新最后登录时间
    await UserMySQL.updateLastLogin(user.id);

    res.json(success({
      user: UserMySQL.sanitize(user),
      token,
      refreshToken,
      message: '登录成功'
    }));
  } catch (error) {
    next(error);
  }
};

// 获取当前用户信息
const getCurrentUser = async (req, res, next) => {
  try {
    const user = await UserMySQL.findById(req.userId);
    if (!user) {
      throw new AppError('用户不存在', 404);
    }

    res.json(success({
      user: UserMySQL.sanitize(user)
    }));
  } catch (error) {
    next(error);
  }
};

// 更新用户信息
const updateProfile = async (req, res, next) => {
  try {
    const { nickname, avatar, gender, birthday } = req.body;
    const updates = {};

    if (nickname !== undefined) updates.nickname = nickname;
    if (avatar !== undefined) updates.avatar = avatar;
    if (gender !== undefined) updates.gender = gender;
    if (birthday !== undefined) updates.birthday = birthday;

    const success = await UserMySQL.update(req.userId, updates);
    if (!success) {
      throw new AppError('更新失败', 400);
    }

    const user = await UserMySQL.findById(req.userId);

    res.json(success({
      user: UserMySQL.sanitize(user),
      message: '个人信息更新成功'
    }));
  } catch (error) {
    next(error);
  }
};

// 修改密码
const changePassword = async (req, res, next) => {
  try {
    const { currentPassword, newPassword } = req.body;

    if (!currentPassword || !newPassword) {
      throw new AppError('当前密码和新密码不能为空', 400);
    }

    if (newPassword.length < 6) {
      throw new AppError('新密码长度不能少于6位', 400);
    }

    const user = await UserMySQL.findById(req.userId);
    if (!user) {
      throw new AppError('用户不存在', 404);
    }

    // 验证当前密码
    const isCurrentPasswordValid = await bcrypt.compare(currentPassword, user.password);
    if (!isCurrentPasswordValid) {
      throw new AppError('当前密码错误', 401);
    }

    // 加密新密码
    const hashedPassword = await bcrypt.hash(newPassword, 12);

    // 更新密码
    await UserMySQL.updatePassword(req.userId, hashedPassword);

    res.json(success({
      message: '密码修改成功'
    }));
  } catch (error) {
    next(error);
  }
};

// 微信登录/注册
const wechatLogin = async (req, res, next) => {
  try {
    const { code, userInfo } = req.body;

    if (!code) {
      throw new AppError('微信授权码不能为空', 400);
    }

    // 这里应该调用微信API获取openid和unionid
    // 模拟获取微信用户信息
    const wechatUserInfo = {
      openid: `mock_openid_${Date.now()}`,
      unionid: `mock_unionid_${Date.now()}`,
      nickname: userInfo?.nickName || '微信用户',
      avatar: userInfo?.avatarUrl || '',
      gender: userInfo?.gender === 1 ? 'male' : userInfo?.gender === 2 ? 'female' : 'unknown'
    };

    // 查找是否已存在微信用户
    let user = await UserMySQL.findByWechatOpenid(wechatUserInfo.openid);

    if (user) {
      // 更新最后登录时间
      await UserMySQL.updateLastLogin(user.id);
    } else {
      // 创建新用户（微信注册）
      const randomPassword = Math.random().toString(36).slice(-8);
      const hashedPassword = await bcrypt.hash(randomPassword, 12);

      const userId = await UserMySQL.create({
        username: `wx_${wechatUserInfo.openid.slice(-8)}`,
        password: hashedPassword,
        nickname: wechatUserInfo.nickname,
        avatar: wechatUserInfo.avatar,
        gender: wechatUserInfo.gender,
        wechatOpenid: wechatUserInfo.openid,
        wechatUnionid: wechatUserInfo.unionid
      });

      user = await UserMySQL.findById(userId);
    }

    // 生成token
    const token = generateToken(user.id);

    res.json(success({
      user: UserMySQL.sanitize(user),
      token,
      message: '微信登录成功'
    }));
  } catch (error) {
    next(error);
  }
};

// 管理员登录
const adminLogin = async (req, res, next) => {
  try {
    const { username, password } = req.body;

    if (!username || !password) {
      throw new AppError('用户名和密码不能为空', 400);
    }

    // 查找用户（支持用户名、邮箱、手机号登录）
    let user = await UserMySQL.findByUsername(username);
    if (!user) {
      user = await UserMySQL.findByEmail(username);
    }
    if (!user) {
      user = await UserMySQL.findByPhone(username);
    }

    if (!user) {
      throw new AppError('用户不存在', 404);
    }

    // 检查用户状态
    if (!UserMySQL.isActive(user)) {
      throw new AppError('账户已被禁用', 403);
    }

    // 检查用户是否为管理员（假设level >= 2为管理员）
    if (user.level < 2) {
      throw new AppError('权限不足，需要管理员权限', 403);
    }

    // 验证密码
    const isPasswordValid = await bcrypt.compare(password, user.password_hash);
    if (!isPasswordValid) {
      throw new AppError('密码错误', 401);
    }

    // 生成token
    const token = generateToken(user.id);

    // 更新最后登录时间
    await UserMySQL.updateLastLogin(user.id);

    // 调整返回数据结构以匹配前端期望的格式
    res.json(success({
      token,
      admin: UserMySQL.sanitize(user),
      message: '管理员登录成功'
    }));
  } catch (error) {
    next(error);
  }
};

// 刷新Token
const refreshToken = async (req, res, next) => {
  try {
    const { refreshToken } = req.body;

    if (!refreshToken) {
      throw new AppError('刷新token不能为空', 400);
    }

    // 验证刷新token
    const decoded = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET || 'your-refresh-secret-key');
    
    if (decoded.type !== 'refresh') {
      throw new AppError('无效的刷新token', 401);
    }

    // 查找用户
    const user = await UserMySQL.findById(decoded.userId);
    if (!user) {
      throw new AppError('用户不存在', 404);
    }

    // 检查用户状态
    if (!UserMySQL.isActive(user)) {
      throw new AppError('账户已被禁用', 403);
    }

    // 生成新的访问token
    const newToken = generateToken(user.id);

    res.json(success({
      token: newToken,
      message: 'Token刷新成功'
    }));
  } catch (error) {
    if (error.name === 'JsonWebTokenError') {
      throw new AppError('无效的刷新token', 401);
    }
    
    if (error.name === 'TokenExpiredError') {
      throw new AppError('刷新token已过期', 401);
    }

    next(error);
  }
};

// 发送邮箱验证码
const sendEmailVerification = async (req, res, next) => {
  try {
    const { email } = req.body;

    if (!email) {
      throw new AppError('邮箱不能为空', 400);
    }

    // 检查邮箱格式
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(email)) {
      throw new AppError('邮箱格式不正确', 400);
    }

    // 生成验证码
    const verificationCode = generateVerificationCode();
    const expiresAt = new Date(Date.now() + 10 * 60 * 1000); // 10分钟后过期

    // 保存验证码到数据库（这里需要创建一个验证码表）
    await UserMySQL.saveVerificationCode(email, verificationCode, expiresAt);

    // 发送邮件
    await sendEmail({
      to: email,
      subject: '结伴客 - 邮箱验证',
      html: `
        <h2>邮箱验证</h2>
        <p>您的验证码是：<strong>${verificationCode}</strong></p>
        <p>验证码将在10分钟后过期，请及时使用。</p>
        <p>如果这不是您的操作，请忽略此邮件。</p>
      `
    });

    res.json(success({
      message: '验证码已发送到您的邮箱'
    }));
  } catch (error) {
    next(error);
  }
};

// 忘记密码
const forgotPassword = async (req, res, next) => {
  try {
    const { email } = req.body;

    if (!email) {
      throw new AppError('邮箱不能为空', 400);
    }

    // 查找用户
    const user = await UserMySQL.findByEmail(email);
    if (!user) {
      // 为了安全，不暴露用户是否存在
      res.json(success({
        message: '如果该邮箱已注册，重置密码链接已发送到您的邮箱'
      }));
      return;
    }

    // 生成重置token
    const resetToken = generateVerificationCode();
    const expiresAt = new Date(Date.now() + 30 * 60 * 1000); // 30分钟后过期

    // 保存重置token
    await UserMySQL.savePasswordResetToken(user.id, resetToken, expiresAt);

    // 发送重置邮件
    await sendEmail({
      to: email,
      subject: '结伴客 - 密码重置',
      html: `
        <h2>密码重置</h2>
        <p>您请求重置密码，请点击下面的链接重置您的密码：</p>
        <a href="${process.env.FRONTEND_URL}/reset-password?token=${resetToken}">重置密码</a>
        <p>此链接将在30分钟后过期。</p>
        <p>如果这不是您的操作，请忽略此邮件。</p>
      `
    });

    res.json(success({
      message: '如果该邮箱已注册，重置密码链接已发送到您的邮箱'
    }));
  } catch (error) {
    next(error);
  }
};

// 重置密码
const resetPassword = async (req, res, next) => {
  try {
    const { token, newPassword } = req.body;

    if (!token || !newPassword) {
      throw new AppError('重置token和新密码不能为空', 400);
    }

    if (newPassword.length < 6) {
      throw new AppError('密码长度不能少于6位', 400);
    }

    // 验证重置token
    const resetData = await UserMySQL.findPasswordResetToken(token);
    if (!resetData || new Date() > resetData.expires_at) {
      throw new AppError('重置token无效或已过期', 400);
    }

    // 加密新密码
    const hashedPassword = await bcrypt.hash(newPassword, 12);

    // 更新密码
    await UserMySQL.updatePassword(resetData.user_id, hashedPassword);

    // 删除重置token
    await UserMySQL.deletePasswordResetToken(token);

    res.json(success({
      message: '密码重置成功'
    }));
  } catch (error) {
    next(error);
  }
};

module.exports = {
  register,
  login,
  getCurrentUser,
  updateProfile,
  changePassword,
  wechatLogin,
  adminLogin,
  refreshToken,
  sendEmailVerification,
  forgotPassword,
  resetPassword
};