package com.judong.chuanyiserver.service.impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.judong.chuanyiserver.dao.UserDao;
import com.judong.chuanyiserver.entity.Role;
import com.judong.chuanyiserver.entity.User;
import com.judong.chuanyiserver.enums.ResultEnum;
import com.judong.chuanyiserver.exception.CustomException;
import com.judong.chuanyiserver.service.UserService;
import com.judong.chuanyiserver.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private UserUtil userUtil;

    @Override
    public Result getCodeImage(boolean hasPubKey) {
        JSONObject jsonObject = new JSONObject();
        // 定义图形验证码的长、宽、验证码字符数、干扰线宽度
        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(126, 40, 4, 4);
        // 图形验证码写出，可以写出到文件，也可以写出到流
        String captchaCode = captcha.getCode();
        HttpServletRequest request = userUtil.getRequest();
        String sessionId = request.getRequestedSessionId();
        if (Blank.isEmpty(sessionId)) {
            sessionId = request.getSession().getId();
        }
        // 设置验证码有效时间
        redisUtil.set(sessionId + "-captcha", captchaCode, ConstantStr.ONE_MINUTE);
        jsonObject.put("uid", sessionId);
        jsonObject.put("verifyCode", captcha.getImageBase64());
        if (hasPubKey) {
            jsonObject.put("publicKey", RSAUtil.PUBLIC_KEY);
        }
        return Result.ok(jsonObject);
    }

    /**
     * 前端用户登录
     *
     * @param user
     * @return
     */
    @Override
    public Result frontUserLogin(User user) {
        try {
            user.setPassword(RSAUtil.decrypt(user.getPassword(), "UTF-8"));
        } catch (Exception e) {
            throw new CustomException(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), ResultEnum.REQUEST_WRONGPARAMS.getRespMsg());
        }
        User isExistUser = userDao.getUserByNamePass(user.getUserName(), EncryptUtils.StrToMD5(user.getPassword()));
        if (Blank.isEmpty(isExistUser)) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户名或密码错误");
        }
        if (isExistUser.getUserType() != ConstantStr.FRONT_USER) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "请使用客户端账号登录");
        }
        // 校验验证码
        String storeCode = Convert.toStr(redisUtil.get(user.getUid() + "-captcha"));
        if (Blank.isEmpty(storeCode)) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "验证码失效，请重新获取验证码");
        }
        if (!user.getVerifyCode().equals(storeCode)) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "输入的验证码不正确");
        }
        // 验证码通过则删除验证码
        redisUtil.del(user.getUid() + "-captcha");
        switch (isExistUser.getState()) {
            case ConstantStr.NORMAL_USE:
                JSONObject json = new JSONObject();
                isExistUser.setPassword("");
                //生成token
                String token = TokenUtil.token(isExistUser.getUserName(), ConstantStr.HALF_HOUR);
                json.put("token", token);
                redisUtil.set(token, isExistUser.getUserId(), ConstantStr.HALF_HOUR);
                isExistUser.setRoleList(userDao.getRoleListByUserId(isExistUser.getUserId()));
                json.put("user", isExistUser);
                //更新用户登录状态
                if (userDao.updateLoginState(isExistUser.getUserId()) <= 0) {
                    return Result.no(ResultEnum.SERVER_ERROR.getRespCode(), "更新登录状态失败");
                }
                return Result.ok(json);
            case ConstantStr.LOCK_USER:
                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户已被锁定，请联系管理员");
            case ConstantStr.TOMBSTONE:
                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户已被删除，请联系管理员");
            default:
                throw new CustomException(ResultEnum.UNKNOWN_ERROR.getRespCode(), "用户状态不在系统设置列中");
        }
    }

    /**
     * 后台管理系统登录
     *
     * @param user
     * @return
     */
    @Override
    public Result backUserLogin(User user) {
        try {
            user.setPassword(RSAUtil.decrypt(user.getPassword(), "UTF-8"));
        } catch (Exception e) {
            throw new CustomException(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), ResultEnum.REQUEST_WRONGPARAMS.getRespMsg());
        }
        User isExistUser = userDao.getUserByNamePass(user.getUserName(), EncryptUtils.StrToMD5(user.getPassword()));
        if (Blank.isEmpty(isExistUser)) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户名或密码错误");
        }
        if (isExistUser.getUserType() != ConstantStr.BACK_USER) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "请使用后台管理账号登录");
        }
        // 校验验证码
        String storeCode = Convert.toStr(redisUtil.get(user.getUid() + "-captcha"));
        if (Blank.isEmpty(storeCode)) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "验证码失效，请重新获取验证码");
        }
        if (!user.getVerifyCode().equals(storeCode)) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "输入的验证码不正确");
        }
        // 验证码通过则删除验证码
        redisUtil.del(user.getUid() + "-captcha");
        switch (isExistUser.getState()) {
            case ConstantStr.NORMAL_USE:
                List<Role> roleList = userDao.getRoleListByUserId(isExistUser.getUserId());
                JSONObject json = new JSONObject();
                isExistUser.setPassword("");
                isExistUser.setRoleList(roleList);
                json.put("user", isExistUser);
                //生成token
                String token = TokenUtil.token(isExistUser.getUserName(), ConstantStr.HALF_HOUR);
                json.put("token", token);
                redisUtil.set(token, isExistUser.getUserId(), ConstantStr.HALF_HOUR);
                return Result.ok(json);
            case ConstantStr.LOCK_USER:
                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户已被锁定，请联系管理员");
            case ConstantStr.TOMBSTONE:
                return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户已被删除，请联系管理员");
            default:
                throw new CustomException(ResultEnum.UNKNOWN_ERROR.getRespCode(), "用户状态不在系统设置列中");
        }
    }

    /**
     * 添加用户
     *
     * @param user
     * @return
     */
    @Override
    public synchronized Result addUser(User user) {
        if (user.getUserType() != ConstantStr.FRONT_USER && user.getUserType() != ConstantStr.BACK_USER) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户类型只能为客户端和后台用户");
        }
        User isExistUser = userDao.getUserByName(user.getUserName());
        if (Blank.isNotEmpty(isExistUser)) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "该用户名已被使用，请更换其他用户名");
        }
        String userId = UUID.randomUUID().toString().replaceAll("-", "");
        user.setUserId(userId);
        try {
            user.setPassword(EncryptUtils.StrToMD5(RSAUtil.decrypt(user.getPassword(), "UTF-8")));
        } catch (Exception e) {
            throw new CustomException(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), ResultEnum.REQUEST_WRONGPARAMS.getRespMsg());
        }
        if (userDao.addUser(user) <= 0) {
            return Result.no(ResultEnum.SERVER_ERROR.getRespCode(), "新增失败");
        }
        //新增用户默认角色为2
        if (userDao.addUserRole(userId, ConstantStr.ROLE_STAFF) <= 0) {
            return Result.no(ResultEnum.SERVER_ERROR.getRespCode(), "新增失败");
        }
        return Result.ok("添加用户成功");
    }

    @Override
    public synchronized Result assignRole(String userId, List<Role> roleList) {
        //查询出拥有新旧角色集合拥有的公共角色
        List<Role> shareRoleList = userDao.getShareRoleList(userId, roleList);
        //增加新增的角色信息
        List<Role> newRoleList = new ArrayList<>();
        if (Blank.isEmpty(shareRoleList)) {
            newRoleList = roleList;
            //删除原来的角色
            userDao.deleteUserRoleByUserId(userId);
        } else {
            for (int i = 0; i < roleList.size(); i++) {
                Boolean flage = false;
                for (int j = 0; j < shareRoleList.size(); j++) {
                    if (roleList.get(i).getId() == shareRoleList.get(j).getId()) {
                        flage = true;
                        break;
                    }
                }
                if (!flage) {
                    newRoleList.add(roleList.get(i));
                }
            }
            //删除不在公共角色的旧角色Id
            List<Role> oldRoleList = userDao.getNoShareOldRoleList(userId, shareRoleList);
            if (Blank.isNotEmpty(oldRoleList)) {
                userDao.deleteUserRole(userId, oldRoleList);
            }
        }
        if (Blank.isNotEmpty(newRoleList)) {
            userDao.addUserRoleList(userId, newRoleList);
        }
        return Result.ok("分配角色成功");
    }

    @Override
    public Result userLoginOut() {
        String token = userUtil.getToken();
        redisUtil.del(token);
        return Result.ok(true);
    }

    @Override
    public Result getUserPage(int page, int limit, String userName, Integer state, Integer userType) {
        JSONObject jsonObject = new JSONObject();
        Long count = userDao.getUserCount(userName, state, userType, ConstantStr.TOMBSTONE);
        Long startNum = Long.valueOf((page - 1) * limit);
        List<User> userList = userDao.getUserPage(startNum, Long.valueOf(limit), userName, state, userType, ConstantStr.TOMBSTONE);
        jsonObject.put("count", count);
        jsonObject.put("userList", userList);
        return Result.ok(jsonObject);
    }

    @Override
    public Result getUserById(String userId) {
        String tokenUserId = userUtil.getCurrentUserId();
        List<Role> roleList = userDao.getRoleListByUserId(tokenUserId);
        for (Role role : roleList) {
            if (role.getId() == ConstantStr.ROLE_ADMIN) {
                User user = userDao.getUserById(userId);
                user.setRoleList(userDao.getRoleListByUserId(userId));
                return Result.ok(user);
            }
        }
        if (userId.equals(tokenUserId)) {
            User user = userDao.getUserById(userId);
            user.setRoleList(roleList);
            return Result.ok(user);
        }
        return Result.no(ResultEnum.NO_OPERATION_AUTHORITY.getRespCode(), ResultEnum.NO_OPERATION_AUTHORITY.getRespMsg());
    }

    @Override
    public synchronized Result updateUserStateById(String userId, Integer userState) {
        if (userState != ConstantStr.NORMAL_USE && userState != ConstantStr.LOCK_USER) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户状态参数只能指定为正常和锁定");
        }
        String msg = "";
        switch (userState) {
            case ConstantStr.NORMAL_USE:
                msg = "用户变更为正常用户";
                if (userDao.updateUserState(userId, userState) <= 0) {
                    return Result.no(ResultEnum.SERVER_ERROR.getRespCode(), msg + "失败");
                }
                return Result.ok(msg + "成功");
            case ConstantStr.LOCK_USER:
                msg = "userState";
                if (userDao.updateUserState(userId, userState) <= 0) {
                    return Result.no(ResultEnum.SERVER_ERROR.getRespCode(), msg + "失败");
                }
                return Result.ok(msg + "成功");
            default:
                throw new CustomException(ResultEnum.UNKNOWN_ERROR.getRespCode(), "用户状态参数只能指定为正常和锁定");
        }
    }

    @Override
    public synchronized Result deleteUserById(String userId) {
        if (userDao.updateUserState(userId, ConstantStr.TOMBSTONE) <= 0) {
            return Result.no(ResultEnum.SERVER_ERROR.getRespCode(), "删除用户失败");
        }
        return Result.ok("删除用户成功");
    }

    @Override
    public synchronized Result updateUser(User user) {
        if (Blank.isEmpty(user.getUserId(), user.getUserName(), user.getState(), user.getUserType())) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "用户Id不能为空，用户名不能为空,用户状态不能为空，用户类型不能为空");
        }
        if (Blank.isNotEmpty(userDao.getUserByNameNoId(user.getUserId(), user.getUserName()))) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), "该用户名已被使用，请更换其他用户名");
        }
        if (user.getState() == ConstantStr.TOMBSTONE) {
            return Result.no(ResultEnum.REQUEST_WRONGPARAMS.getRespCode(), ResultEnum.REQUEST_WRONGPARAMS.getRespMsg());
        }
        if (userDao.updateUser(user) <= 0) {
            return Result.no(ResultEnum.SERVER_ERROR.getRespCode(), "修改用户失败");
        }
        return Result.ok("修改用户成功");
    }

}
