package com.ruoyi.web.controller.common;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import com.ruoyi.common.core.domain.model.AppRegisterUser;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.controller.app.baidu.BaiduSMS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.*;
import com.google.code.kaptcha.Producer;
import com.ruoyi.common.config.RuoYiConfig;
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.uuid.IdUtils;
import com.ruoyi.system.service.ISysConfigService;

import static com.ruoyi.common.core.domain.AjaxResult.error;
import static com.ruoyi.common.core.domain.AjaxResult.success;

/**
 * 验证码操作处理
 *
 * @author ruoyi
 */
@RestController
public class CaptchaController {

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


    @Resource(name = "captchaProducer")
    private Producer captchaProducer;

    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ISysConfigService configService;


    @Autowired
    private ISysUserService sysUserService;

    /**
     * 生成验证码
     */
    @GetMapping("/captchaImage")
    public AjaxResult getCode(HttpServletResponse response) throws IOException {
        AjaxResult ajax = AjaxResult.success();
        boolean captchaEnabled = configService.selectCaptchaEnabled();
        ajax.put("captchaEnabled", captchaEnabled);
        if (!captchaEnabled) {
            return ajax;
        }

        // 保存验证码信息
        String uuid = IdUtils.simpleUUID();
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;

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

        // 生成验证码
        String captchaType = RuoYiConfig.getCaptchaType();
        if ("math".equals(captchaType)) {
            String capText = captchaProducerMath.createText();
            capStr = capText.substring(0, capText.lastIndexOf("@"));
            code = capText.substring(capText.lastIndexOf("@") + 1);
            image = captchaProducerMath.createImage(capStr);
        } else if ("char".equals(captchaType)) {
            capStr = code = captchaProducer.createText();
            image = captchaProducer.createImage(capStr);
        }

        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());
        }

        ajax.put("uuid", uuid);
        ajax.put("img", Base64.encode(os.toByteArray()));
        return ajax;
    }


    /**
     * 注册： 获取验证码
     * @param phone
     * @return
     * @throws IOException
     */
    @GetMapping("/appCaptchaCode/{phone}")
    public AjaxResult getAppRegisterCode(@PathVariable String phone) throws IOException {
        AjaxResult ajax = AjaxResult.success();

        // 注册时可能出现多次获取验证码的情况，不应该在这里判断手机号是否注册。
//        //先验证手机号是否已经注册
//        int i = sysUserService.checkUserPhone(phone);
//        if (i > 0) {
//            return AjaxResult.error("该手机号已经注册");
//        }
        // 保存验证码信息
//        String uuid = IdUtils.simpleUUID();

        //发送验证码
        sendCacheCode(phone);
        return AjaxResult.success(phone);
    }
    @PostMapping("/registerCheckPhone")
    public AjaxResult registerCheckPhone(@RequestBody AppRegisterUser user){
        String username = user.getUsername();
        int i = sysUserService.checkUserPhone(username);
        if (i > 0) {
            return error("该手机号已经注册");
        }
        else{
            sendCacheCode(username);
            return success("验证码已发送");
        }
    }
    @PostMapping("/verifyRegisterSms")
    public AjaxResult verifyRegisterSMS(@RequestBody AppRegisterUser user) {
        String username = user.getUsername();
        String code = user.getCode();
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(username, "");
        String captcha = redisCache.getCacheObject(verifyKey);

//        String backCode = redisCache.getCacheObject(username);
        if (captcha == null) {
            return error("验证码已过期");
        }
        else if (!code.equalsIgnoreCase(captcha)){
            return error("验证码错误");
        }
        else{
            redisCache.deleteObject(verifyKey);
            return success("验证码正确");
        }
//        return success("验证码正确");
    }
//    @GetMapping("/appUpdatePasswordCaptchaCode/{phone}")
//    public AjaxResult getUpdatePasswordCode(@PathVariable String phone) throws IOException {
//        AjaxResult ajax = AjaxResult.success();
//
//        // 保存验证码信息
////        String uuid = IdUtils.simpleUUID();
//        sendCacheCode(phone);
//        return AjaxResult.success(phone);
//    }


    /**
     * 登录_修改：获取验证码
     * @param phone
     * @return
     * @throws IOException
     */
    @GetMapping("/appLoginCaptchaCode/{phone}")
    public AjaxResult getAppLoginCode(@PathVariable String phone) throws IOException {
        AjaxResult ajax = AjaxResult.success();
        //先验证手机号是否注册 注册的才可以通过手机号验证登录
        int i = sysUserService.checkUserPhone(phone);
        if (i == 0) {
            return AjaxResult.error("该手机号尚未注册");
        }
        // 保存验证码信息
//        String uuid = IdUtils.simpleUUID();
        sendCacheCode(phone);
        return AjaxResult.success(phone);
    }

    // 按理来说不同类型的验证码，应该有不同的缓存key，这里为了方便，就都用一个缓存key了
    private void sendCacheCode(String phone) {
        try {
            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + phone;

            String countKey = CacheConstants.CAPTCHA_CODE_KEY_COUNT + phone;
            // 生成短信验证码
            Random random = new Random();
//            String testCode = String.format("%04d", random.nextInt(10000)); // 0000-9999
            String testCode = "1234"; // 0000-9999
            // Constants.CAPTCHA_EXPIRATION 为验证码过期时间，这里是5
            redisCache.setCacheObject(verifyKey, testCode, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);

            // 记录验证码尝试次数
            redisCache.setCacheObject(countKey, 0, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);

            // 发送验证码
//            boolean flag = BaiduSMS.sendSMS(phone, testCode, "5");
            boolean flag = true;
            if (flag) {
                log.info("发送短信验证码成功:"+phone);
                System.out.println("发送短信验证码成功"+testCode);
            } else {
                log.info("发送短信验证码异常:"+phone);
//                System.out.println("发送短信验证码失败");
            }
        } catch (Exception e) {
            log.info("发送短信验证码异常:" + e.getMessage());
            e.printStackTrace();
        }

    }
}
