package com.jiayue.ssi.controller;

import com.jiayue.ssi.config.SendMailUtil;
import com.jiayue.ssi.constant.CacheConstants;
import com.jiayue.ssi.constant.CustomException;
import com.jiayue.ssi.entity.SysMenu;
import com.jiayue.ssi.entity.SysUser;
import com.jiayue.ssi.service.SysMenuService;
import com.jiayue.ssi.service.SysUserService;
import com.jiayue.ssi.util.*;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户登录控制类
 *
 * @author xsl
 * @since 2023/02/20
 */
@RestController
@Slf4j
public class UserLoginController {
    @Autowired
    SysUserService sysUserService;
    @Autowired
    JwtTokenUtil jwtTokenUtil;
    @Autowired
    SendMailUtil sendMailUtil;
    @Autowired
    SysMenuService sysMenuService;

    /**
     * 生成验证码
     *
     * @param httpServletResponse
     * @throws IOException
     */
    @GetMapping("/getVerifyCode")
    public ResponseVO getVerifyCode(String murmur,HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws CustomException {
        // 三个参数分别为宽、高、位数
        try {
            if (murmur.length()!=32){
                return ResponseVO.fail("不能生成验证码！");
            }
            String textcode = "";
            String base64 = "";
            while (true) {
                SpecCaptcha captcha = new SpecCaptcha(150, 40, 4);
                /**
                 * 验证码字符类型 TYPE_DEFAULT 数字和字母混合 TYPE_ONLY_NUMBER 纯数字 TYPE_ONLY_CHAR 纯字母 TYPE_ONLY_UPPER 纯大写字母 TYPE_ONLY_LOWER
                 * 纯小写字母 TYPE_NUM_AND_UPPER 数字和大写字母
                 **/
                // 设置类型 数字和字母混合
                captcha.setCharType(Captcha.TYPE_DEFAULT);
                // 设置字体
                captcha.setCharType(Captcha.FONT_9);
                int digits = 0;
                char[] text = captcha.textChar();
                for (int i = 0; i < text.length; i++) {
                    if (Character.isDigit(text[i])) {
                        digits++;
                    }
                }
                if (digits == 0 || digits == 4) {
                    // 重新生成
                } else {
                    textcode = String.valueOf(text);
                    base64 = captcha.toBase64();
                    break;
                }
            }

            String uuid = IdUtils.simpleUUID();
            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid+murmur;
            // uuid存入缓存，失效时间默认5分钟
            LocalCache.set(verifyKey, textcode);
            // 输出图片流
            // captcha.out(httpServletResponse.getOutputStream());

            int index = base64.indexOf(",");
            String substring = base64.substring(index + 1);

            Map<String, String> dataMap = new HashMap<>(16);
            dataMap.put("uuid", uuid);
            dataMap.put("imgBase64", substring);
            dataMap.put("captchaText", textcode);
            return ResponseVO.success(dataMap);
        } catch (Exception e) {
            throw new CustomException("生成验证码异常", e);
        }
    }

    /**
     * 获取邮箱口令
     *
     * @param httpServletRequest
     * @param httpServletResponse
     * @throws IOException
     */
    @GetMapping("/getMailCode")
    public ResponseVO getMailCode(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws CustomException {
        try {
            String username = httpServletRequest.getParameter("username");
            // 口令保存到服务器
            String mailKey = CacheConstants.MAIL_CODE_KEY + username;
            SysUser sysUser = sysUserService.queryUserName(username);
            if (sysUser != null) {
                // 生成6位邮箱口令
                String mailRandom = RandomUtil.mailRandom();
                // uuid存入缓存，失效时间4分钟
                LocalCache.set(mailKey, mailRandom, 60000 * 4);
                try {
                    String[] mailArray = {AesUtils.decryptStr(sysUser.getMailbox())};
                    sendMailUtil.executeSendMail(mailArray, "邮箱验证码", "口令：" + mailRandom + ",有效期4分钟。");
                } catch (Exception e) {
                    log.error("用户名："+username+",邮箱验证码发送失败！",e);
                    return ResponseVO.fail("邮箱验证码发送失败！");
                }
            }
            return ResponseVO.success();
        } catch (Exception e) {
            throw new CustomException("获取邮箱口令异常", e);
        }
    }

    /**
     * 刷新token
     *
     * @param httpServletRequest
     * @param httpServletResponse
     * @throws IOException
     */
    @PostMapping("/refreshToken")
    public ResponseVO refreshToken(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws CustomException {
        try {
            String oldToken = httpServletRequest.getHeader("Authorization");
            String newToken = jwtTokenUtil.refreshToken(oldToken);
            CacheConstants.LOGIN_TOKEN_MAP.put(SecurityContextUtil.getSysUser().getUsername(), newToken);
            return ResponseVO.success(newToken);
        } catch (Exception e) {
            throw new CustomException("刷新token异常", e);
        }
    }

    /**
     * 获取路由菜单信息
     *
     * @return 路由菜单信息
     */
    @GetMapping("getRouters")
    public ResponseVO getRouters() throws CustomException {
        try {
            Long userId = SecurityContextUtil.getSysUser().getId();
            List<SysMenu> menus = sysMenuService.selectMenuTreeByUserId(userId);
            return ResponseVO.success(sysMenuService.buildMenus(menus));
        } catch (Exception e) {
            throw new CustomException("获取路由菜单信息异常", e);
        }
    }
}
