package com.ruoyi.hezhi.api.kaoshi;

import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.alibaba.fastjson2.JSONObject;
import com.google.code.kaptcha.Producer;
import com.ruoyi.common.annotation.RateLimiter;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.txy.TencentSmsCodeUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.common.weixin.config.WeiXinPayConfig;
import com.ruoyi.hezhi.domain.dto.MemberUserLoginDTO;
import com.ruoyi.hezhi.domain.dto.SmsCodeDTO;
import com.ruoyi.hezhi.domain.dto.StudentDTO;
import com.ruoyi.hezhi.service.ITbSmsCodeService;
import com.ruoyi.hezhi.service.ITbStudentService;
import io.swagger.annotations.Api;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * @Author: LCL
 * @Date: 2024/10/08
 * @Description:通用API
 */
@Api("登录")
@RestController
@RequestMapping("/api/login")
public class ApiLoginController {

    private static final Logger log = LoggerFactory.getLogger(ApiLoginController.class);

    @Resource
    private RedisCache redisCache;
    @Resource(name = "captchaProducer")
    private Producer captchaProducer;
    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;
    @Resource
    private ITbStudentService studentService;
    @Resource
    private ITbSmsCodeService smsCodeService;
    @Resource
    private WeiXinPayConfig weiXinPayConfig;
    @Resource
    ITbStudentService tbStudentService;


    /**
     * 发送验证码
     *
     * @param smsCodeDTO 参数
     * @return 结果
     */
    @RepeatSubmit
    @RateLimiter(key = "API_sendSmsCode")
    @PostMapping("/sendSmsCode")
    public AjaxResult sendSmsCode(@RequestBody @Validated({SmsCodeDTO.sendSmsCode.class}) SmsCodeDTO smsCodeDTO, BindingResult bindingResult) {
        // 参数校验
        if (bindingResult.hasErrors()) {
            return AjaxResult.allParameterErrors(bindingResult);
        }
        try {
            // 生成验证码
            String smsCode = IdUtils.buildNumberCode(6);
//            TencentSmsCodeUtils tencentSmsCodeUtils = new TencentSmsCodeUtils();
//            String result = tencentSmsCodeUtils.sendSmsCode(smsCodeDTO.getPhone(), smsCode);
            String result = "SUCCESS";
            if ("SUCCESS".equals(result)) {
                return smsCodeService.sendSmsCodeInsert(smsCodeDTO.getPhone(), smsCode, smsCodeDTO.getType());
            }
            return AjaxResult.error();
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("发送验证码异常");
        }
    }

    /**
     * 生成图片验证码
     */
    @GetMapping("/getCaptchaImage")
    public AjaxResult getCaptchaImage() {
        // 保存验证码信息
        String uuid = IdUtils.simpleUUID();
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;

        String capStr = null, code = null;
        BufferedImage image = null;

        // 生成验证码
        capStr = code = captchaProducer.createText();
        image = captchaProducer.createImage(capStr);

        if (image == null) {
            return AjaxResult.error("验证码生成异常");
        }

        redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);

        // 转换流信息写出
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpg", os);
        } catch (IOException e) {
            return AjaxResult.error(e.getMessage());
        }

        HashMap<String, Object> map = new HashMap<>();
        map.put("uuid", uuid);
        map.put("img", Base64.encode(os.toByteArray()));
        return AjaxResult.success(map);
    }

    /**
     * 扫码登陆轮询
     * @param studentDTO 参数
     * @return 结果
     */
    @RateLimiter(key = "API_userCodeLogin")
    @PostMapping("/userCodeLogin")
    public AjaxResult userCodeLogin(@RequestBody @Validated({StudentDTO.userCodeLogin.class}) StudentDTO studentDTO, BindingResult bindingResult) {
        // 参数校验
        if (bindingResult.hasErrors()) {
            return AjaxResult.allParameterErrors(bindingResult);
        }
        return studentService.userCodeLogin(studentDTO);
    }

    /**
     * 手机号登录
     *
     * @param studentDTO 参数
     * @return 结果
     */
    @RepeatSubmit
    @RateLimiter(key = "API_userPhoneLogin")
    @PostMapping("/userPhoneLogin")
    public AjaxResult userPhoneLogin(@RequestBody @Validated({StudentDTO.userPhoneLogin.class}) StudentDTO studentDTO, BindingResult bindingResult) {
        // 参数校验
        if (bindingResult.hasErrors()) {
            return AjaxResult.allParameterErrors(bindingResult);
        }
        try {
            return studentService.userPhoneLogin(studentDTO);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("手机号登录异常");
        }
    }

    /**
     * 身份证号码登录
     *
     * @param studentDTO 参数
     * @return 结果
     */
    @RepeatSubmit
    @RateLimiter(key = "API_userIdentityCardLogin")
    @PostMapping("/userIdentityCardLogin")
    public AjaxResult userIdentityCardLogin(@RequestBody @Validated({StudentDTO.userIdentityCardLogin.class}) StudentDTO studentDTO, BindingResult bindingResult) {
        // 参数校验
        if (bindingResult.hasErrors()) {
            return AjaxResult.allParameterErrors(bindingResult);
        }
        try {
            return studentService.userIdentityCardLogin(studentDTO);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("手机号登录异常");
        }
    }

    /**
     * 找回密码
     *
     * @param studentDTO 参数
     * @return 结果
     */
    @RepeatSubmit
    @RateLimiter(key = "API_userRetrievePassword", time = 5, count = 50)
    @PostMapping("/userRetrievePassword")
    public AjaxResult userRetrievePassword(@RequestBody @Validated({StudentDTO.userRetrievePassword.class}) StudentDTO studentDTO, BindingResult bindingResult) {
        // 参数校验
        if (bindingResult.hasErrors()) {
            return AjaxResult.allParameterErrors(bindingResult);
        }
        try {
            return studentService.userRetrievePassword(studentDTO);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("找回密码异常");
        }
    }

    /**
     * 微信登录二维码
     *
     * @param
     * @return 结果
     */
    @GetMapping("/wxLoginQRCode")
    public AjaxResult wxLoginQRCode() {
        System.out.println("____________________--wxLogin");

        //redirect_url是回调地址 注意要转换成UrlEncode格式
        String redirectUrl = null;
        try {
            redirectUrl = URLEncoder.encode("https://web.xuexin.com/wxCallback","UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //构造二维码链接地址
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+weiXinPayConfig.getAppIdLogin()+"&redirect_uri="+redirectUrl+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";

        QrConfig config = new QrConfig(300, 300);
        // 设置边距，既二维码和背景之间的边距
        config.setMargin(3);
        // 设置前景色，既二维码颜色（黑色）
        config.setForeColor(Color.black);
        // 设置背景色（灰色）
        config.setBackColor(Color.white);
        // 生成二维码到文件，也可以到流
        BufferedImage image = QrCodeUtil.generate(url, config);

        //将newImage写入字节数组输出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpg", baos );
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取字节数组
        byte[] data = baos.toByteArray();
        String base64String = java.util.Base64.getEncoder().encodeToString(data);
        HashMap<Object, Object> map = new HashMap<>();
        map.put("qrcodeUrlBase64", base64String);

        return AjaxResult.success(map);
    }

    /**
     * 微信登录二维码 登录
     *
     * @param
     * @return 结果
     */
    // @GetMapping("/callback")
    // public AjaxResult callback(String code, String state) {
    //     // 获取code值，拿着 code 请求微信固定地址，得到 accsess_token 和 openId
    //     String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
    //             "?appid=%s" +
    //             "&secret=%s" +
    //             "&code=%s" +
    //             "&grant_type=authorization_code";
    //     String accessTokenUrl = String.format(baseAccessTokenUrl,
    //             weiXinPayConfig.getAppIdLogin(),
    //             weiXinPayConfig.getAppSecretLogin(),
    //             code);
    //     String result = restTemplate.getForObject(accessTokenUrl, String.class);
    //     HashMap<String, String> hashMap = JSON.parseObject(result, HashMap.class);
    //     String accessToken = hashMap.get("access_token");
    //     String openid = hashMap.get("openid");
    //     log.info("token：{}，openid：{}", accessToken, openid);
    //
    //     // 查询数据库当前用用户是否曾经使用过微信登录
    //     TbStudent tbStudent = studentService.selectTbStudentByOpenId(openid);
    //     if (tbStudent == null) {
    //         log.info("新用户注册");
    //         //访问微信的资源服务器，获取用户信息
    //         String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
    //                 "?access_token=%s" +
    //                 "&openid=%s";
    //         String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);
    //         String resultUserInfo = null;
    //         resultUserInfo = restTemplate.getForObject(userInfoUrl, String.class);
    //
    //         log.info("用户信息：{}", resultUserInfo);
    //         //解析json
    //         HashMap<String, Object> mapUserInfo = JSON.parseObject(resultUserInfo, HashMap.class);
    //         // 获取微信名
    //         String nickname = (String) mapUserInfo.get("nickname");
    //         // 获取头像
    //         String headimgurl = (String) mapUserInfo.get("headimgurl");
    //         //向数据库中插入一条记录
    //         TbStudent student = new TbStudent();
    //         student.setNickName(nickname);
    //         student.setOpenid(openid);
    //         student.setHeadPortrait(headimgurl);
    //         studentService.insertTbStudent(student);
    //     }
    //     HashMap<String, Object> map = new HashMap<>();
    //     map.put("tbStudent", studentService.selectTbStudentByOpenId(openid));
    //     return AjaxResult.success(map);
    // }


    /**
     * 小程序授权登录
     *
     * @param memberUserLoginDTO 参数
     * @return 结果
     */
    @RepeatSubmit
    @PostMapping("/memberUserLogin")
    public AjaxResult memberUserLogin(@RequestBody @Validated({MemberUserLoginDTO.MemberUserLogin.class}) MemberUserLoginDTO memberUserLoginDTO, BindingResult bindingResult) {
        // 参数校验
        if (bindingResult.hasErrors()) {
            return AjaxResult.allParameterErrors(bindingResult);
        }

        JSONObject jsonObject = tbStudentService.memberUserLogin(memberUserLoginDTO);
        return AjaxResult.success(jsonObject);
    }

    /**
     * 小程序注册
     *
     * @param memberUserLoginDTO 参数
     * @return 结果
     */
    @RepeatSubmit
    @PostMapping("/memberUserRegister")
    public AjaxResult memberUserRegister(@RequestBody @Validated({MemberUserLoginDTO.MemberUserRegister.class}) MemberUserLoginDTO memberUserLoginDTO, BindingResult bindingResult) {
        // 参数校验
        if (bindingResult.hasErrors()) {
            return AjaxResult.allParameterErrors(bindingResult);
        }

        JSONObject jsonObject = tbStudentService.memberUserRegister(memberUserLoginDTO);
        return AjaxResult.success(jsonObject);
    }

}
