package com.dcsoft.auth.controller;

import com.dcsoft.auth.service.SysAuthService;
import com.dcsoft.common.core.constant.CacheConstants;
import com.dcsoft.common.core.utils.JwtUtils;
import com.dcsoft.common.core.utils.StringUtils;
import com.dcsoft.common.core.web.domain.AjaxResult;
import com.dcsoft.common.core.web.page.TableDatasInfo;
import com.dcsoft.common.redis.service.RedisService;
import com.dcsoft.system.api.domain.FaceStudentBody;
import com.dcsoft.system.api.domain.SysAuth;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * token 控制
 *
 * @author dcsoft
 */
@RestController
@RequestMapping("/face-api")
public class ApiController
{
    @Autowired
    private RedisService redisService;

    @Autowired
    private SysAuthService sysAuthService;


    /**
     * 鉴权接口
     */
    @GetMapping("/auth")
    public AjaxResult auth(HttpServletRequest request)
    {
        String timestamp=request.getHeader("timestamp");
        String appKey=request.getHeader("appKey");
        String sign=request.getHeader("sign");
        if(StringUtils.isEmpty(timestamp)){
            return AjaxResult.error("timestamp is empty");
        }
        Long timeLong=new Date().getTime()/1000-Long.parseLong(timestamp);
        if(timeLong>5*60){
            return AjaxResult.error("timestamp is timeOut");
        }
        if(StringUtils.isEmpty(appKey)){
            return AjaxResult.error("appKey is empty");
        }
        if(StringUtils.isEmpty(sign)){
            return AjaxResult.error("sign is empty");
        }
        //appSecret通过后台获取
        SysAuth auth=sysAuthService.getAuth(appKey);
        String appSecret=auth.getAppSecret();
        String sign1= EncodeByMD5(appKey+timestamp+appSecret).toLowerCase();
        //比较两次秘钥的sign的值是否一致
        if(sign.equals(sign1)){
            //根据appKey生成token
            // Jwt存储信息
            Map<String, Object> claimsMap = new HashMap<String, Object>();
            String verifyKey = CacheConstants.AUTH_KEY + appKey;
            claimsMap.put(CacheConstants.AUTH_KEY, appKey);
            String token =JwtUtils.createToken(claimsMap);
            redisService.setCacheObject(verifyKey,token);
            redisService.expire(verifyKey,24*60*60);
            return AjaxResult.success("token get success",token);
        }else{
            return AjaxResult.error("sign create error");
        }
    }

    /**
     * 人脸信息接口
     */
    @PostMapping("/faceInfo")
    public TableDatasInfo faceInfo(HttpServletRequest request)
    {
        TableDatasInfo msg=new TableDatasInfo();

        String token=request.getHeader("token");
        Boolean flag=validate(token);
        if(flag){
            String phone=request.getParameter("phone");
            String idCard=request.getParameter("id_card");
            String label=request.getParameter("label");
            String pageNum=request.getParameter("pageNum");
            String pageSize=request.getParameter("pageSize");
            if(StringUtils.isEmpty(pageNum)){
                pageNum="1";
            }
            if(StringUtils.isEmpty(pageSize)){
                pageSize="10";
            }
            String endTime=request.getParameter("endTime");
            String startTime=request.getParameter("startTime");
            FaceStudentBody faceStudent=new FaceStudentBody();
            faceStudent.setPhone(phone);
            faceStudent.setIdCard(idCard);
            faceStudent.setPageNum(pageNum);
            faceStudent.setPageSize(pageSize);
            faceStudent.setLabel(label);
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-HH-mm");
            try {
                if(StringUtils.isNotEmpty(startTime)){
                    faceStudent.setStartTime(sdf.parse(startTime));
                }
                if(StringUtils.isNotEmpty(endTime)){
                    faceStudent.setEndTime(sdf.parse(endTime));
                }
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            msg=sysAuthService.studentList(faceStudent);
        }else{
            msg.setCode(500);
            msg.setMsg("token is timeOut or is error");
        }

        return msg;
    }


    public Boolean validate(String token){
        if (StringUtils.isEmpty(token)){
            return false;
        }
        Claims claims = JwtUtils.parseToken(token);
        if (claims == null)
        {
            return false;
        }
        String appKey=JwtUtils.getValue(claims,CacheConstants.AUTH_KEY);
        //所有请求 token 及其他参数都写在 header 中
        String verifyKey = CacheConstants.AUTH_KEY + appKey;
        String tokens = redisService.getCacheObject(verifyKey);
        if(StringUtils.isEmpty(tokens)) {//重新获取token
            return false;
        }
        if(token.equals(tokens)){
            return true;
        }else{
            return false;
        }
    }



    /**
     * 对字符串进行32位MD5加密
     * @param str
     * @return
     */
    public static String EncodeByMD5(String str) {
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(str.getBytes("UTF-8"));
            // digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
            String md5=new BigInteger(1, md.digest()).toString(16);
            //BigInteger会把0省略掉，需补全至32位
            return fillMD5(md5);
        } catch (Exception e) {
            throw new RuntimeException("MD5加密错误:"+e.getMessage(),e);
        }
    }

    private static String fillMD5(String md5) {
        //如果不够32位则回调自身补零，最后返回32位长度的签名
        return md5.length() == 32 ? md5 : fillMD5("0" + md5);
    }


}
