const Router = require('@koa/router');
const router = new Router({ prefix: '/api/user' });
const util = require('../utils/util');
const userService = require('../service/user.service');
const projectService = require('../service/projects.service');
const projectUserService = require('../service/project.user.service');
const pageRoleService = require('../service/pagesRole.service');
const pageService = require('../service/pages.service');
const menuService = require('../service/menu.service');
const publishService = require('../service/publish.service');
const roleService = require('../service/roles.service');
const imgcloudService = require('../service/imgcloud.service');
const md5 = require('md5.js');
const nodemailer = require('nodemailer');
const config = require('../config');
const request = require('../utils/request');
const { Keyv } = require('keyv');
const keyv = new Keyv();
/**
 * 用户登录
 */
router.post('/login', async (ctx) => {
  const { userName, userPwd, openId } = ctx.request.body;
  if (!userName || !userPwd) {
    util.fail(ctx, '用户名或密码不能为空');
    return;
  }
  const pwd = new md5().update(userPwd).digest('hex');
  const res = await userService.findUser(userName, pwd, openId || userName);

  if (!res) {
    util.fail(ctx, '用户名或密码错误');
    return;
  }
  if (!res.openId && openId) {
    const cacheUser = await keyv.get(openId);
    if (cacheUser) {
      await userService.bindOpenId({ ...cacheUser, id: res.id });
    }
  }

  const token = util.createToken({ userName, userId: res.id, nickName: res.nickName });
  userService.updateUserInfo(res.id);
  util.success(ctx, {
    userId: res.id,
    userName,
    token,
  });
});

/**
 * 微信授权登录
 */
router.post('/wechat', async (ctx) => {
  const { code } = ctx.request.body;
  if (!code) {
    util.fail(ctx, 'code不能为空');
    return;
  }
  const response = await request.get(
    `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${config.WECHAT_APP_ID}&secret=${config.WECHAT_APP_SECRET}&code=${code}&grant_type=authorization_code`,
    {},
  );
  const { access_token, openid, unionid, errcode } = JSON.parse(response.data);
  if (errcode) {
    util.success(ctx, '');
    return;
  }
  const wxUser = await userService.findUser(openid, openid, openid);
  if (wxUser) {
    userService.updateUserInfo(wxUser.id);
    const token = util.createToken({ userName: wxUser.userName, userId: wxUser.id, nickName: wxUser.nickName });
    util.success(ctx, {
      userId: wxUser.id,
      userName: wxUser.userName,
      token,
    });
    return;
  }

  const res1 = await request.get(`https://api.weixin.qq.com/sns/userinfo?access_token=${access_token}&openid=${openid}`);
  const { nickname, headimgurl } = JSON.parse(res1.data);
  await keyv.set(
    openid,
    {
      openid,
      unionid,
      nickname,
      headimgurl,
    },
    3 * 60 * 1000,
  );
  util.success(ctx, {
    openId: openid,
  });
});

/**
 * 获取用户信息
 */
router.get('/info', async (ctx) => {
  const { userId } = util.decodeToken(ctx);
  const res = await userService.profile(userId);
  util.success(ctx, res);
});

/**
 * 获取个人信息
 */
router.get('/profile', async (ctx) => {
  const { userId } = util.decodeToken(ctx);
  const res = await userService.profile(userId);
  util.success(ctx, res);
});
/**
 * 用户搜索
 */
router.post('/search', async (ctx) => {
  const { keyword } = ctx.request.body;
  if (!keyword) {
    util.fail(ctx, '关键字不能为空');
    return;
  }
  const res = await userService.search(keyword);
  if (!res) {
    util.fail(ctx, '当前用户名不存在');
    return;
  }
  util.success(ctx, res);
});

/**
 * 用户信息更新
 */
router.post('/update/profile', async (ctx) => {
  const { nickName, avatar } = ctx.request.body;
  if (!nickName && !avatar) {
    util.fail(ctx, '参数异常,请重新提交');
    return;
  }
  const { userId } = util.decodeToken(ctx);
  await userService.updateUserInfo(userId, nickName, avatar);
  util.success(ctx, '更新成功');
});

/**
 * 用户注册 - 发送验证码
 */
router.post('/sendEmail', async (ctx) => {
  try {
    const { email } = ctx.request.body;
    if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
      util.fail(ctx, '邮箱不能为空或格式错误');
      return;
    }
    const val = await keyv.get(email);
    if (val) {
      util.fail(ctx, '验证码已发送,请查收');
      return;
    }
    let transporter = nodemailer.createTransport({
      host: config.EMAIL_HOST,
      port: config.EMAIL_PORT,
      auth: {
        user: config.EMAIL_USER, // 你的Gmail地址
        pass: config.EMAIL_PASSWORD, // 你的Gmail密码或应用专用密码
      },
    });

    const random = Math.random().toString().slice(2, 7).replace(/^(0)+/, '1');

    let mailOptions = {
      from: `"Marsview" <${config.EMAIL_USER}>`, // 发送者地址
      to: email, // 接收者列表
      subject: 'Marsview账号注册', // 主题行
      text: '验证码发送', // 纯文字正文
      html: `当前验证码为:<b>${random}</b>,3分钟内有效。<br/><br/>感谢您体验 Marsview 搭建平台,线上平台不保证数据的稳定性,建议有条件用户,切换到 Marsview 私有化部署服务,您在使用过程中遇到任何问题均联系我。<br/><br/>邮  箱:marsview@163.com<br/>微  信:17611021717`, // HTML正文
    };

    await transporter.sendMail(mailOptions);
    await keyv.set(email, random, 3 * 60 * 1000);
    util.success(ctx, '发送成功');
  } catch (error) {
    util.fail(ctx, error.message);
  }
});

/**
 * 用户注册
 */
router.post('/regist', async (ctx) => {
  const { userName, code, userPwd } = ctx.request.body;
  if (!userName || !userPwd) {
    util.fail(ctx, '用户名或密码不能为空');
    return;
  }
  if (!code) {
    util.fail(ctx, '邮箱验证码不能为空');
    return;
  }
  const val = await keyv.get(userName);
  if (!val) {
    util.fail(ctx, '验证码已过期');
    return;
  }
  if (val != code) {
    util.fail(ctx, '验证码错误');
    return;
  }
  const user = await userService.search(userName);
  if (user) {
    util.fail(ctx, '当前用户已存在');
    return;
  }

  const nickName = userName.split('@')[0];
  const pwd = new md5().update(userPwd).digest('hex');
  const res = await userService.create(nickName, userName, pwd);
  if (res.affectedRows == 1) {
    // 生成用户token
    const token = util.createToken({ userName, userId: res.insertId });

    util.success(ctx, {
      userId: res.id,
      userName,
      token,
    });
  } else {
    util.fail(ctx, '注册失败,请重试');
  }
});

/**
 * 忘记密码 - 生成链接
 */
router.post('/password/forget', async (ctx) => {
  const { userEmail } = ctx.request.body;
  if (!userEmail) {
    util.fail(ctx, '邮箱不能为空');
    return;
  }
  const user = await userService.search(userEmail);
  if (!user) {
    util.fail(ctx, '当前用户不存在');
    return;
  }
  // 生成验证码,保存在redis中,用来验证链接有效期
  const random = Math.random().toString().slice(2, 7);
  await keyv.set(userEmail, random, 5 * 60 * 1000);
  // 生成加密后token
  const token = util.createToken({ userEmail });

  // 发送邮件
  let transporter = nodemailer.createTransport({
    host: config.EMAIL_HOST,
    port: config.EMAIL_PORT,
    auth: {
      user: config.EMAIL_USER, // 你的Gmail地址
      pass: config.EMAIL_PASSWORD, // 你的Gmail密码或应用专用密码
    },
  });
  let mailOptions = {
    from: `"Marsview" <${config.EMAIL_USER}>`, // 发送者地址
    to: userEmail, // 接收者列表
    subject: 'Marsview密码找回', // 主题行
    text: '验证码发送', // 纯文字正文
    html: `Hello,${userEmail}! <br/> 我们收到了你重置密码的申请,请点击下方按链接行重置,<a href="https://www.marsview.com.cn/password-reset?resetToken=${token}">重置密码</a> <br/> 链接 3分钟内有效,请尽快操作,如不是你发起的请求,请忽略。`, // HTML正文
  };

  await transporter.sendMail(mailOptions);
  util.success(ctx, '发送成功');
});

/**
 * 忘记密码 - 获取账号
 */
router.post('/password/getUserByToken', async (ctx) => {
  const { resetToken } = ctx.request.query;
  const { userEmail } = util.decodeResetToken(resetToken);
  const val = await keyv.get(userEmail);
  if (!val) {
    util.fail(ctx, '链接已失效,请重新操作');
    return;
  }
  util.success(ctx, userEmail);
});

/**
 * 忘记密码 - 重置密码
 */
router.post('/password/reset', async (ctx) => {
  const { resetToken, userPwd } = ctx.request.body;
  if (!resetToken) {
    util.fail(ctx, '重置Token不能为空');
    return;
  }
  if (!userPwd) {
    util.fail(ctx, '重置密码不能为空');
    return;
  }
  const { userEmail } = util.decodeResetToken(resetToken);
  if (!userEmail) {
    util.fail(ctx, 'Token 识别错误,请重新操作');
    return;
  }
  const val = await keyv.get(userEmail);
  if (!val) {
    util.fail(ctx, '链接已失效,请重新操作');
    return;
  }
  const pwd = new md5().update(userPwd).digest('hex');
  await userService.resetPwd(userEmail, pwd);
  await keyv.delete(userEmail);
  util.success(ctx, '更新成功');
});

/**
 * 密码修改
 */

router.post('/password/update', async (ctx) => {
  const { oldPwd, userPwd, confirmPwd } = ctx.request.body;
  if (!oldPwd || !userPwd || !confirmPwd) {
    util.fail(ctx, '密码不能为空');
    return;
  }
  if (userPwd !== confirmPwd) {
    util.fail(ctx, '两次密码不一致');
    return;
  }
  const { userName } = util.decodeToken(ctx);

  try {
    const res = await userService.verifyOldPwd(userName, oldPwd);
    if (res) {
      const pwd = new md5().update(userPwd).digest('hex');
      await userService.resetPwd(userName, pwd);
      util.success(ctx, '密码更改成功');
    } else {
      util.fail(ctx, '原密码输入错误');
    }
  } catch (error) {
    util.fail(ctx, error.message);
  }
});

/**
 * 用户注销
 */
router.post('/logout', async (ctx) => {
  const { userId, userName } = util.decodeToken(ctx);
  if (userId == 50) {
    util.fail(ctx, '管理员账号不支持注销');
    return;
  }
  // 删除用户所有项目
  await projectService.deleteAllProject(userId, userName);
  // 删除用户所有关联
  await projectUserService.deleteAllProjectUser(userId);
  // 删除用户所有页面角色
  await pageRoleService.deleteAllPageRole(userId);
  // 删除用户所有页面
  await pageService.deleteAllPage(userId, userName);
  // 删除用户所有菜单
  await menuService.deleteAllMenu(userId);
  // 删除用户所有发布
  await publishService.deleteAllPublish(userId);
  // 删除用户所有角色
  await roleService.deleteAllRole(userId);
  // 删除用户
  await userService.deleteUser(userId, userName);
  // 删除用户图片
  await imgcloudService.deleteAllImg(userId);
  util.success(ctx, '注销成功');
});

/**
 * 查询子用户列表
 */
router.get('/subUser/list', async (ctx) => {
  const { userId } = util.decodeToken(ctx);
  const { pageNum, pageSize, keyword } = ctx.request.query;
  const { total } = await userService.getSubUsersCount(userId, keyword);
  if (total == 0) {
    return util.success(ctx, {
      list: [],
      total: 0,
      pageSize: +pageSize || 12,
      pageNum: +pageNum || 1,
    });
  }
  const list = await userService.getSubUsersList(userId, pageNum || 1, pageSize || 12, keyword);

  util.success(ctx, {
    list,
    total,
    pageSize: +pageSize,
    pageNum: +pageNum,
  });
});

// 创建子用户
router.post('/subUser/create', async (ctx) => {
  const { userName, userPwd } = ctx.request.body;
  if (!userName || !userPwd) {
    util.fail(ctx, '用户名或密码不能为空');
    return;
  }
  const { userId } = util.decodeToken(ctx);

  const user = await userService.search(userName);
  if (user) {
    util.fail(ctx, '当前用户已存在');
    return;
  }

  const nickName = userName.split('@')[0];
  const pwd = new md5().update(userPwd).digest('hex');
  const res = await userService.create(nickName, userName, pwd, userId);
  if (res.affectedRows == 1) {
    util.success(ctx, '注册成功');
  } else {
    util.fail(ctx, '注册失败,请重试');
  }
});

// 删除子用户
router.post('/subUser/delete', async (ctx) => {
  const { id } = ctx.request.body;
  if (!id) {
    util.fail(ctx, '用户ID不能为空');
    return;
  }
  const { userId } = util.decodeToken(ctx);
  const res = await userService.deleteSubUser(id, userId);
  if (res.affectedRows == 1) {
    util.success(ctx, '删除成功');
  } else {
    util.fail(ctx, '删除失败,请重试');
  }
});
module.exports = router;