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.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.xxfc.platform.universal.entity.IdInformation;
import com.xxfc.platform.universal.mapper.IdInformationMapper;
import com.xxfc.platform.universal.utils.CertifHttpUtils;
import com.xxfc.platform.universal.utils.Validation;
import javafx.application.Application;
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.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
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.*;


@Service
@Slf4j
public class CertificationService {
    /**
     * 认证相关的数据
     */
    @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是认证过

        //判断是否map是否为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.createDefaultFail();
        }


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

        Map frontData = (Map) frontMap.get(dataNam);

        Map backData = (Map) backMap.get(dataNam);


        if (MapUtil.isEmpty(backData) || MapUtil.isEmpty(frontData)) {

            return ObjectRestResponse.createDefaultFail();
        }

        //解析通过,进行匹配

        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.调用接口进行认证
        String result = certificate(authMap);
        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))) {

                //认证成功后存入保存到数据库
                //获得身份证正面记录的身份证号和真实姓名

                //设置姓名
                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.createDefaultFail();
                    }
                }
                idInformation.setExpirationDate(expirationDate);
                CertificationService cs = applicationContext.getBean(this.getClass());
                ObjectRestResponse objRR =cs.addIdInformation(idInformation);
                log.info("----请求admin=========" + objRR);
                if (objRR.getRel()) {
                    return ObjectRestResponse.succ(objRR.getData());
                }

            }
        }


        return ObjectRestResponse.succ();


    }


    //认证
    public String 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) {
                return EntityUtils.toString(response.getEntity());
            }

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


        }
        return null;
    }


    //身份证照片解析
    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("userLonginId",idInformation.getUserLonginId());
            List<IdInformation> idInformations = idInformationMapper.selectByExample(exa);
            if (CollectionUtils.isEmpty(idInformations)) {
                idInformation.setCrtTime(new Date());
                idInformationMapper.insertSelective(idInformation);
            }else {
                IdInformation idInformation1 = idInformations.get(0);
                idInformation.setId(idInformation1.getId());
                idInformation.setUpdTime(new Date());
                idInformationMapper.updateByPrimaryKeySelective(idInformation);
            }
            log.info("----addIdInformation---userid==="+idInformation.getUserLonginId()+"----name====" + idInformation.getName()+"---IdNumber==="+idInformation.getIdNumber());
            //认证成功后修改用户,用户认证状态
            ObjectRestResponse authentication = userFeign.authentication(idInformation.getUserLonginId(), idInformation.getName(), idInformation.getIdNumber(), 1);
           return ObjectRestResponse.succ(idInformation.getId());
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus();
            return ObjectRestResponse.createDefaultFail();
        }




    }



}




