package com.bonus.canteen.core.customer.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.canteen.core.common.utils.SysUtil;
import com.bonus.canteen.core.customer.dto.BitmainOtherInfoDTO;
import com.bonus.canteen.core.customer.dto.BitmainResultDTO;
import com.bonus.canteen.core.customer.dto.UfaceResultDTO;
import com.bonus.canteen.core.customer.dto.UnifiedFaceRegisterParamDTO;
import com.bonus.canteen.core.customer.metadata.model.FaceMetadataModel;
import com.bonus.canteen.core.customer.metadata.service.FaceMetadataService;
import com.bonus.canteen.core.customer.model.CustInfo;
import com.bonus.canteen.core.customer.service.CustInfoService;
import com.bonus.canteen.core.customer.service.FaceRegisterService;
import com.bonus.canteen.core.customer.utils.BitmainUtil;
import com.bonus.canteen.core.customer.utils.UfaceUtil;
import com.bonus.canteen.core.customer.v4.dto.FaceRegisterDTO;
import com.bonus.canteen.core.customer.v4.megvii.MegviiUtilV4;
import com.bonus.canteen.core.customer.vo.MultiModelFaceVO;
import com.bonus.canteen.core.device.constants.FaceVerTypeEnum;
import com.bonus.common.houqin.utils.LeBeanUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;

@Service
public class FaceRegisterServiceImpl implements FaceRegisterService {
   private static final Logger log = LoggerFactory.getLogger(FaceRegisterServiceImpl.class);
   @Resource
   CustInfoService custInfoService;
   @Resource
   private FaceMetadataService faceMetadataService;

   public Optional<BitmainResultDTO> registerBitmain(String imageBase64, BitmainOtherInfoDTO registerParamDTO) {
      FaceMetadataModel faceMetadataModel = this.faceMetadataService.queryMetadata();
      if (!ObjectUtil.isEmpty(faceMetadataModel) && !"2".equals(faceMetadataModel.getIfUseBitFaceBoxUrl())) {
         List<String> serverUrls = (List)Optional.ofNullable(faceMetadataModel.getBitFaceBoxUrl()).map((settingValue) -> {
            return JSON.parseArray(settingValue, String.class);
         }).orElse(new ArrayList());
         if (!CollUtil.isNotEmpty(serverUrls)) {
            log.info("未配置比特大陆盒子!");
            return Optional.empty();
         } else {
            boolean checkResult = serverUrls.stream().anyMatch((url) -> {
               return !Pattern.matches("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]):([0-9]|[1-9]\\d|[1-9]\\d{2}|[1-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$", url);
            });
            BitmainResultDTO bitmainResultDTO;
            if (checkResult) {
               bitmainResultDTO = (new BitmainResultDTO()).setSuccess(false).setMsg("比特大陆地址格式错误!");
            } else {
               Iterator var7 = serverUrls.iterator();

               while(var7.hasNext()) {
                  String serverUrl = (String)var7.next();

                  try {
                     String[] elements = serverUrl.split(":");
                     UriComponents uriComponent = UriComponentsBuilder.newInstance().scheme("http").host(elements[0]).port(elements[1]).path("{template}").build();
                     JSONObject resJson = BitmainUtil.registerFaceQuick(imageBase64, registerParamDTO, uriComponent);
                     if (!resJson.containsKey("data")) {
                        if (resJson.containsKey("error")) {
                           log.info("比特盒子注册失败,返回信息：{}", resJson);
                           bitmainResultDTO = (new BitmainResultDTO()).setSuccess(false).setMsg(resJson.getJSONObject("error").getString("chinese_message"));
                           return Optional.ofNullable(bitmainResultDTO);
                        }

                        bitmainResultDTO = (new BitmainResultDTO()).setSuccess(false).setMsg(resJson.toJSONString());
                        return Optional.ofNullable(bitmainResultDTO);
                     }

                     JSONObject dataJson = resJson.getJSONObject("data");
                     if (dataJson.containsKey("feature")) {
                        dataJson.remove("feature");
                        log.info("比特盒子注册成功，返回信息：{}", dataJson);
                     }
                  } catch (Exception var13) {
                     log.error("", var13);
                     if (var13 instanceof IORuntimeException) {
                        bitmainResultDTO = (new BitmainResultDTO()).setSuccess(false).setMsg("请求超时！");
                     } else {
                        bitmainResultDTO = (new BitmainResultDTO()).setSuccess(false).setMsg(var13.getMessage());
                     }

                     return Optional.ofNullable(bitmainResultDTO);
                  }
               }

               bitmainResultDTO = (new BitmainResultDTO()).setSuccess(true);
            }

            return Optional.ofNullable(bitmainResultDTO);
         }
      } else {
         log.info("未配置或未启用比特大陆盒子!");
         return Optional.empty();
      }
   }

   public Optional<UfaceResultDTO> registerUface(String imageBase64, Long custId) {
      FaceMetadataModel faceMetadataModel = this.faceMetadataService.queryMetadata();
      if (!ObjectUtil.isEmpty(faceMetadataModel) && !"2".equals(faceMetadataModel.getIfUseGateMachineUrl())) {
         String serverUrl = faceMetadataModel.getGateMachineUrl();
         String pwd = faceMetadataModel.getGateMachinePwd();
         if (StrUtil.isNotEmpty(serverUrl) && StrUtil.isNotEmpty(pwd)) {
            JSONObject deleteResObj = UfaceUtil.delFace(pwd, custId, serverUrl);
            UfaceResultDTO result;
            if (!BooleanUtil.isTrue(deleteResObj.getBoolean("success")) && !"LAN_EXP-4017".equals(deleteResObj.getString("code"))) {
               result = (new UfaceResultDTO()).setSuccess(false).setMsg(deleteResObj.getString("msg"));
            } else {
               result = this.getGateMachineResultDTO(serverUrl, pwd, custId, imageBase64);
            }

            return Optional.ofNullable(result);
         } else {
            log.info("未配置宇泛闸机算法！");
            return Optional.empty();
         }
      } else {
         log.info("未配置或未启用宇泛闸机算法！");
         return Optional.empty();
      }
   }

   private UfaceResultDTO getGateMachineResultDTO(String serverUrl, String pwd, Long custId, String imageBase64) {
      JSONObject createFaceResObj = UfaceUtil.createFace(pwd, serverUrl, custId, imageBase64);
      if (BooleanUtil.isTrue(createFaceResObj.getBoolean("success"))) {
         return (new UfaceResultDTO()).setSuccess(true);
      } else if ("LAN_EXP-3009".equals(createFaceResObj.getString("code"))) {
         CustInfo custInfo = (CustInfo)this.custInfoService.getOne((Wrapper)Wrappers.lambdaQuery(CustInfo.class).eq(CustInfo::getCustId, custId));
         JSONObject createPersonResObj = UfaceUtil.createCust(custInfo, pwd, serverUrl);
         if (BooleanUtil.isTrue(createPersonResObj.getBoolean("success"))) {
            return BooleanUtil.isTrue(UfaceUtil.createFace(pwd, serverUrl, custId, imageBase64).getBoolean("success")) ? (new UfaceResultDTO()).setSuccess(true) : (new UfaceResultDTO()).setSuccess(false).setMsg("闸机人脸二次注册失败！");
         } else {
            return (new UfaceResultDTO()).setSuccess(false).setMsg(createPersonResObj.getString("msg"));
         }
      } else {
         return (new UfaceResultDTO()).setSuccess(false).setMsg(createFaceResObj.getString("msg"));
      }
   }


   @Override
   public List<MultiModelFaceVO> multiModelRegisterHandler(UnifiedFaceRegisterParamDTO registerParamDTO, boolean isSaveErrorPicture) {
      List<MultiModelFaceVO> list = new ArrayList();
      FaceMetadataModel faceMetadataModel = this.faceMetadataService.queryMetadata();
      if (!ObjectUtil.isEmpty(faceMetadataModel) && (!"2".equals(faceMetadataModel.getIfUseBitFaceBoxUrl()) || !"2".equals(faceMetadataModel.getIfUseGateMachineUrl()) || !"2".equals(faceMetadataModel.getIfUseMegvii1109FaceUrl()) || !"2".equals(faceMetadataModel.getIfUseMegvii3288FaceUrl()) || !"2".equals(faceMetadataModel.getIfUseMegvii3568FaceUrl()))) {
         BitmainOtherInfoDTO bitmainOtherInfoDTO = (BitmainOtherInfoDTO)BeanUtil.copyProperties(registerParamDTO, BitmainOtherInfoDTO.class, new String[0]);
         Optional<BitmainResultDTO> bitmainResultDTO = this.registerBitmain(registerParamDTO.getImageBase64(), bitmainOtherInfoDTO);
         if (bitmainResultDTO.isPresent()) {
            if (Boolean.FALSE.equals(((BitmainResultDTO)bitmainResultDTO.get()).getSuccess())) {
               SysUtil.removeOssObject(registerParamDTO.getMinioPicPath());
               throw new ServiceException("[比特大陆]：失败");
            }

            MultiModelFaceVO faceVO = MultiModelFaceVO.builder().faceVer(Integer.valueOf(FaceVerTypeEnum.FACE_VER_BIT.getKey())).msg("成功").success(true).build();
            list.add(faceVO);
         }

         Optional<UfaceResultDTO> ufaceResultDTO = this.registerUface(registerParamDTO.getImageBase64(), registerParamDTO.getCustId());
         if (ufaceResultDTO.isPresent()) {
            if (Boolean.FALSE.equals(((UfaceResultDTO)ufaceResultDTO.get()).getSuccess())) {
               SysUtil.removeOssObject(registerParamDTO.getMinioPicPath());
               throw new ServiceException("[宇泛闸机]：失败");
            }

            MultiModelFaceVO faceVO = MultiModelFaceVO.builder().faceVer(Integer.valueOf(FaceVerTypeEnum.FACE_VER_UF.getKey())).msg("成功").success(true).build();
            list.add(faceVO);
         }

         FaceRegisterDTO registerDTO = (FaceRegisterDTO) LeBeanUtil.copyCreateProperties(registerParamDTO, FaceRegisterDTO.class);
         MultiModelFaceVO faceFeature1109;
         if ("1".equals(faceMetadataModel.getIfUseMegvii3288FaceUrl())) {
            registerDTO.setFaceVer(Integer.valueOf(FaceVerTypeEnum.FACE_VER_3288.getKey()));
            registerDTO.setIpFaceAddr(faceMetadataModel.getMegvii3288FaceUrl());
            registerDTO.setServerType(faceMetadataModel.getIfGetMegviiFeature3288Device());
            faceFeature1109 = MegviiUtilV4.generateFaceFeature(registerDTO);
            if (Boolean.FALSE.equals(faceFeature1109.getSuccess()) && !isSaveErrorPicture) {
               SysUtil.removeOssObject(registerParamDTO.getMinioPicPath());
               throw new ServiceException("[旷世3288算法]:失败");
            }

            list.add(faceFeature1109);
         }

         if ("1".equals(faceMetadataModel.getIfUseMegvii3568FaceUrl())) {
            registerDTO.setFaceVer(Integer.valueOf(FaceVerTypeEnum.FACE_VER_3568.getKey()));
            registerDTO.setIpFaceAddr(faceMetadataModel.getMegvii3568FaceUrl());
            registerDTO.setServerType(faceMetadataModel.getIfGetMegviiFeature3568Device());
            faceFeature1109 = MegviiUtilV4.generateFaceFeature(registerDTO);
            if (Boolean.FALSE.equals(faceFeature1109.getSuccess()) && !isSaveErrorPicture) {
               SysUtil.removeOssObject(registerParamDTO.getMinioPicPath());
               throw new ServiceException("[旷世3568算法]:失败" );
            }

            list.add(faceFeature1109);
         }

         if ("1".equals(faceMetadataModel.getIfUseMegvii1109FaceUrl())) {
            if ("1".equals(faceMetadataModel.getIfNoneMegviiFeatureOnlyDevicePhoto())) {
               list.add(MultiModelFaceVO.builder().msg("1109只用照片").success(true).faceVer(Integer.valueOf(FaceVerTypeEnum.FACE_VER_1109.getKey())).feature("").build());
            } else {
               registerDTO.setFaceVer(Integer.valueOf(FaceVerTypeEnum.FACE_VER_1109.getKey()));
               registerDTO.setIpFaceAddr(faceMetadataModel.getMegvii1109FaceUrl());
               registerDTO.setServerType("2");
               faceFeature1109 = MegviiUtilV4.generateFaceFeatureToSoftware(registerDTO);
               if (Boolean.FALSE.equals(faceFeature1109.getSuccess()) && !isSaveErrorPicture) {
                  SysUtil.removeOssObject(registerParamDTO.getMinioPicPath());
                  throw new ServiceException("[旷世1109算法]:失败");
               }

               list.add(faceFeature1109);
            }
         }

         return list;
      } else {
         SysUtil.removeOssObject(registerParamDTO.getMinioPicPath());
         throw new ServiceException("未开启人脸算法，请前往设置-人脸算法配置！");
      }
   }

}
