package com.xxfc.platform.universal.service;


import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.admin.feign.UserFeign;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.xxfc.platform.universal.biz.UserMessage;
import com.xxfc.platform.universal.entity.IdInformation;
import com.xxfc.platform.universal.mapper.IdInformationMapper;
import com.xxfc.platform.universal.service.authenticationInterface.UserAuthentication;
import com.xxfc.platform.universal.utils.CertifHttpUtils;
import com.xxfc.platform.universal.utils.Validation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import tk.mybatis.mapper.entity.Example;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 认证业务
 * @author Administrator
 */
@Service
@Slf4j
public class CertificationService {
    @Autowired
   private UserAuthentication authentication;

    /**
     * 认证相关的数据
     */
    @Value("${certif.cHost}")
    private String cHost;

    @Value("${certif.cPath}")
    private String cPath;

    @Value("${certif.cMethod}")
    private String cMethod;

    @Value("${certif.cAppcode}")
    private String cAppcode;

    //请求:身份证号字段名
    @Value("${certif.idCardName}")
    private String idCardName;

    //请求:用户姓名字段名
    @Value("${certif.cName}")
    private String cName;

    //响应:认证错误码字段名
    @Value("${certif.certifRet}")
    private String certifRet;

    //响应:认证通过码
    @Value("${certif.certifResultCode}")
    private String certifResultCode;


    /**
     * 图片解析相关的数据
     */
    //认证借口host
    @Value("${certif.iHost}")
    private String iHost;

    //认证接口path
    @Value("${certif.iPath}")
    private String iPath;

    //请求方式
    @Value("${certif.iMethod}")
    private String iMethod;

    //认证AppCode(接口商家提供)
    @Value("${certif.iAppcode}")
    private String iAppcode;

    //请求:图片url字段名
    @Value("${certif.picName}")
    private String picName;

    //请求:方向字段名
    @Value("${certif.typeName}")
    private String typeName;

    //请求:反面图片标识  
    @Value("${certif.frontParameter}")
    private String frontParameter;

    //请求:反面图片标识
    @Value("${certif.backParameter}")
    private String backParameter;

    //响应:解析错误码字段名
    @Value("${certif.imageRet}")
    private String imageRet;
    //响应:图片解析错误码
    @Value("${certif.imageResultCode}")
    private String imageResultCode;

    //响应:响应内容字段名
    @Value("${certif.dataNam}")
    private String dataNam;


    //响应:正面身份证号字段名
    @Value("${certif.numberName}")
    private String numberName;


    //响应:正面姓名字段名
    @Value("${certif.iName}")
    private String iName;


    //响应:背面到期时间字段名
    @Value("${certif.expirationDateName}")
    private String expirationDateName;


    @Autowired
    private IdInformationMapper idInformationMapper;


    @Autowired
    private UserFeign userFeign;

    @Autowired
    private ApplicationContext applicationContext;


//     身份证图片进行实名认证

    public  ObjectRestResponse<Integer> certificate(IdInformation idInformation) {
        //1.判断
        //携带返回参数的map
        HashedMap hashMap = new HashedMap();
        // 认证状态:true是认证过
        //判断是否bean是否为null
        if (idInformation == null) {
            return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA, "无法识别,请重新上传");

        }
        //判断是否有填写身份证号
        if (StringUtils.isBlank(idInformation.getIdNumber())) {
            return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA, "未填写证件号");
        }
        if (!Validation.isIdCard(idInformation.getIdNumber())) {
            return ObjectRestResponse.createFailedResult(ResultCode.WRONG_FORMAT_OF_ID_CARD, "填写的证件格式错误");
        }
        //判断是有否填写名字
        if (StringUtils.isBlank(idInformation.getName())) {
            return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA, "未填写姓名");
        }
        //判断是否有正面照片
        if (StringUtils.isBlank(idInformation.getFrontUrl())) {
            return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA, "请上传正面照");
        }
        //判断是否有背面照片
        if (StringUtils.isBlank(idInformation.getBackUrl())) {
            return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA, "请上传背面照");
        }
        //2.解析
        //正面进行解析
        String front = imageParse(idInformation.getFrontUrl(), frontParameter);
        //解析证件背面
        String back = imageParse(idInformation.getBackUrl(), backParameter);
        log.info("----解析front=========" + front);
        log.info("----解析back=========" + back);
        if (StringUtils.isBlank(front) || StringUtils.isBlank(back)) {
            return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA,"无法识别,请重新上传");
        }

        Map frontMap = (Map) JSONObject.parse(front);
        //反面进行解析
        Map backMap = (Map) JSONObject.parse(back);
        //判断是否调用图片解析的接口是否异常,若果两个次认证都没结果
        if (MapUtil.isEmpty(frontMap)
                || !(frontMap.get(imageRet).equals(imageResultCode))
                || MapUtil.isEmpty(backMap)
                || !(backMap.get(imageRet).equals(imageResultCode))
        ) {
            return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA,"无法识别,请重新上传");
        }
        Map frontData = (Map) frontMap.get(dataNam);
        Map backData = (Map) backMap.get(dataNam);
        if (MapUtil.isEmpty(backData) || MapUtil.isEmpty(frontData)) {
            return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA,"无法识别,请重新上传");
        }

        //解析通过,进行匹配
        String name = (String) frontData.get(iName);
        String number = (String) frontData.get(numberName);
        if (idInformation.getName().equals(name)) {
            ObjectRestResponse.createFailedResult(ResultCode.FAILED_CODE, "姓名不一致");
        }
        if (idInformation.getIdNumber().equals(number)) {
            ObjectRestResponse.createFailedResult(ResultCode.FAILED_CODE, "证件号不一致");
        }

        //map携带身份证和姓名进行认证
//        Map<String, String> authMap = new HashMap<>();
//        authMap.put(idCardName, (String) frontData.get(numberName));
//        authMap.put(cName, (String) frontData.get(cName));
//        //3.调用接口进行认证
//
//        boolean result = certificate(authMap);
        boolean result = authentication.certificate(new UserMessage(){{
            setIdNumber(number);
            setName(name);
        }} );
        log.info("----认证结果result=========" + result);
        //认证返回的参数是否为空

            if (result) {
                //认证成功后存入保存到数据库
                //获得身份证正面记录的身份证号和真实姓名
                //设置姓名
                idInformation.setName((String) frontData.get(iName));
                //设置身份证号
                idInformation.setIdNumber((String) frontData.get(numberName));
                //获得到期时间
                String endDate = (String) backData.get(expirationDateName);
                log.info("----获得到期时间endDate=========" + endDate);
                if (StringUtils.isBlank(endDate)) {
                    return ObjectRestResponse.succ();
                }
                Date expirationDate = new Date();
                if (!Validation.isDate(endDate)) {
                    Date date = new Date();
                    Calendar c = Calendar.getInstance();
                    c.setTime(date);
                    c.add(Calendar.YEAR, 100);
                    expirationDate = c.getTime();
                } else {
                    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
                    formatter.setLenient(false);
                    try {
                        expirationDate = formatter.parse(endDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                        return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA,"无法识别,请重新上传");
                    }
                }
                idInformation.setExpirationDate(expirationDate);
                CertificationService cs = applicationContext.getBean(this.getClass());
               return cs.addIdInformation(idInformation);
//                log.info("----请求admin=========" + objRR);
//                if (objRR.getRel()) {
//                    return ObjectRestResponse.succ(objRR.getData());
//                }
            }
        return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA,"网络异常,请稍后再试");


    }


    //认证
    //认证
    public boolean certificate(Map<String, String> querys) {
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Authorization", "APPCODE " + cAppcode);
        try {
            log.info("----querys=========" + querys);
            HttpResponse response = CertifHttpUtils.doGet(cHost, cPath, cMethod, headers, querys);
            StatusLine statusLine = response.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            /**
             * 状态码: 200 正常；400 URL无效；401 appCode错误； 403 次数用完； 500 API网管错误
             */
            //获取response的body
            if (statusCode == 200) {
                String result = EntityUtils.toString(response.getEntity());
                log.info("----认证结果result=========" + result);
                //认证返回的参数是否为空
                if (!StringUtils.isBlank(result)) {
                    Map<String, Object> map = (Map<String, Object>) JSONObject.parse(result);
                    log.info("----certifRet=========" + certifRet);
                    if (MapUtil.isNotEmpty(map) || certifResultCode.equals(map.get(certifRet))) {
                        return true;
                    }
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }



    //身份证照片解析
    public String imageParse(String imageUrl, String type) {
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + iAppcode);
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put(picName, imageUrl);
        //默认正面front，背面请传back
        bodys.put(typeName, type);

        try {
            HttpResponse response = CertifHttpUtils.doPost(iHost, iPath, iMethod, headers, querys, bodys);

            StatusLine statusLine = response.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            log.info("----statusCode=========" + querys);
            /**
             * 状态码: 200 正常；400 URL无效；401 appCode错误； 403 次数用完； 500 API网管错误
             */
            //获取response的body
            if (statusCode == 200) {
                return EntityUtils.toString(response.getEntity());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    //认证通过保存到数据库当中
    @Transactional(rollbackFor = Exception.class)
    public ObjectRestResponse<Integer> addIdInformation(IdInformation idInformation) {
        log.info("----idInformation=========" + idInformation);

        //保存认证信息
        try {
            Example exa = new Example(IdInformation.class);
            Example.Criteria criteria = exa.createCriteria();
            criteria.andEqualTo("idNumber",idInformation.getIdNumber());
//            criteria.andEqualTo("userLoginId",idInformation.getUserLoginId());
            List<IdInformation> idInformatics = idInformationMapper.selectByExample(exa);
            if (CollectionUtils.isEmpty(idInformatics)) {
                idInformation.setCrtTime(new Date());
                idInformationMapper.insertSelective(idInformation);
            }else {
//                IdInformation idInformation1 = idInformatics.get(0);
//                idInformation.setId(idInformation1.getId());
//                idInformation.setUpdTime(new Date());
//                idInformationMapper.updateByPrimaryKeySelective(idInformation);
                log.error("该身份证已存在,不要重复认证");
            return ObjectRestResponse.createFailedResult(ResultCode.FAILED_CODE,"该身份证已存在,不要重复认证");
            }
            log.info("----addIdInformation---userid==="+idInformation.getUserLoginId()+"----name====" + idInformation.getName()+"---IdNumber==="+idInformation.getIdNumber());
            //认证成功后修改用户,用户认证状态
            ObjectRestResponse authentication = userFeign.authentication(idInformation.getUserLoginId(), idInformation.getName(), idInformation.getIdNumber(), 1);
           return ObjectRestResponse.succ(idInformation.getId());
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus();
            return ObjectRestResponse.createFailedResult(ResultCode.INCOMPLETE_DATA,"无法识别,请重新上传");
        }
    }

    public IdInformation getByUser(Integer userId) {
        return idInformationMapper.selectByUserId(userId);
    }

}




