package com.bonus.app.service;

import cn.afterturn.easypoi.cache.manager.IFileLoader;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.shaded.com.google.common.collect.Maps;
import com.bonus.app.config.SystemConfig;
import com.bonus.app.entity.BoxEntity;
import com.bonus.app.entity.BraceletEntity;
import com.bonus.app.entity.BraceletInfoEntity;
import com.bonus.app.entity.LsUserEntity;
import com.bonus.app.mapper.BraceletMapper;
import com.bonus.common.core.constant.BusinessConstants;
import com.bonus.common.core.constant.HttpStatus;
import com.bonus.common.core.constant.SecurityConstants;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.*;
import com.bonus.common.core.utils.encryption.Sm4Utils;
import com.bonus.common.core.utils.uuid.IdUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.entity.bracelet.vo.PersonVo;
import com.bonus.common.entity.file.ResourceFileVo;
import com.bonus.common.security.utils.DictUtils;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.system.api.RemoteFileService;
import com.bonus.system.api.RemoteSourceService;
import com.bonus.system.api.domain.SysDictData;
import com.bonus.system.api.domain.SysFileSource;
import com.bonus.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * app 接口实现层
 */
@Service
@Slf4j
public class BraceletServiceImpl  implements BraceletService{

    @Autowired
    private BraceletMapper mapper;
    @Autowired
    private RemoteFileService fileService;
    @Autowired
    private RemoteSourceService sourceService;

    @Autowired
    private FaceInterUtilService faceInterService;

    @Override
    public AjaxResult getBoxListById(BoxEntity entity) {
       try{
           if (!DateTimeHelper.getNowDay().equals(entity.getCurryDay())) {
               return AjaxResult.error("请求参数不正确");
           }
           setDefaultVal(entity);
           List<BoxEntity> list=mapper.getBoxListById(entity);
           return AjaxResult.success(list);
       }catch (Exception e){
           log.error(e.toString());
       }
        return AjaxResult.error("系统异常");
    }

    /**
     * 查询手环箱信息
     * @param entity
     * @return
     */
    @Override
    public AjaxResult getBoxInfo(BoxEntity entity) {
       try{
           Map<String,Object> map= Maps.newHashMap();
//            if (StringUtils.isEmpty(entity.getBoxId())){
//                return AjaxResult.error("请求参数不正确");
//            }
           setDefaultVal(entity);
            Integer  ffNum=mapper.getBoxFfNum(entity);
           Integer  shUsedNum=mapper.getShUsed(entity);
            //查询手环数据信息
            List<BraceletEntity> list=mapper.getBoxInfo(entity);
            ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
            List<CompletableFuture<?>> futures = new ArrayList<>();
            for(BraceletEntity vo:list){
                   CompletableFuture<?> future = CompletableFuture.runAsync(() -> {
                       List<BraceletInfoEntity>  infoList=mapper.getBoxInfoDetails(vo);
                       //数据处理->高空作业证、数据信息
                       SetDevInfo(infoList,vo);
                       vo.setIdCard(Sm4Utils.decode(vo.getIdCard()));
                       vo.setPhone(Sm4Utils.decode(vo.getPhone()));
                   }, executor);
                   futures.add(future);
               }
           CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0])).join();
            //进行数据处理
           for(BraceletEntity vo:list){
               CompletableFuture<?> future = CompletableFuture.runAsync(() -> {
                   setSgFw(vo);
               }, executor);
               futures.add(future);
           }
           CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0])).join();
           executor.shutdown();
           if(ffNum<=shUsedNum){
               map.put("msg","所发放的手环全部完成绑定");
           }else{
               map.put("msg",ffNum-shUsedNum+"个手环未在规定时间内通过验证,请现场排查");
           }
           map.put("data",list);
           return AjaxResult.success(map);

       }catch (Exception e){
           log.error(e.toString(),e);
       }
        return AjaxResult.error("系统异常");
    }
    @Override
    public AjaxResult getBoxToUser(BoxEntity entity) {
     try{
         Map<String,Object> map=Maps.newHashMap();
         //发放的数量
         Integer  ffNum=mapper.getBoxFfNum(entity);
         //手环箱中手环的数量
         Integer  shNum=mapper.getBoxShNum(entity);
         //手环被使用的数量
         Integer  shUsedNum=mapper.getShUsed(entity);
         map.put("ffNum",ffNum);
         map.put("shNum",shNum);
         map.put("shUsedNum",shUsedNum);
         return AjaxResult.success(map);
     }catch (Exception e){
         log.error(e.toString(),e);
     }
        return AjaxResult.error("系统异常");
    }

    /**
     * 发放手环
     * @param entity
     * @return
     */
    @Override
    public AjaxResult sendBoxBracelet(BoxEntity entity) {
        try{
            if(ObjectUtils.isEmpty(entity.getBoxNum())){
                return AjaxResult.error("发放的数量不能为空");
            }
            if(entity.getBoxNum()==0){
                return AjaxResult.error("发放的数量不能为0");
            }
            //手环箱中手环的数量
            Integer  shNum=mapper.getBoxShNum(entity);
            if(entity.getBoxNum()>shNum){
                return AjaxResult.error("发放的数量不能超过手环箱手环的数量");
            }
             int num=  mapper.updateBoxNum(entity);
            if(num>0){
                return AjaxResult.success("发放成功");
            }
            return AjaxResult.success("发放失败");
        }catch (Exception e){
            log.error(e.toString());
        }
        return AjaxResult.error("系统异常");
    }

    @Override
    public AjaxResult getBoxBraceletUsed(BoxEntity entity) {
        try{
            setDefaultVal(entity);
            //查询 已使用的手环数据信息
            List<BraceletEntity> list=mapper.getBoxInfoBid(entity);
            List<CompletableFuture<?>> futures = new ArrayList<>();
            ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
            for(BraceletEntity vo:list){
                CompletableFuture<?> future = CompletableFuture.runAsync(() -> {
                    List<BraceletInfoEntity>  infoList=mapper.getBoxInfoDetails(vo);
                    //数据处理->高空作业证、数据信息
                    vo.setIdCard(Sm4Utils.decode(vo.getIdCard()));
                    vo.setPhone(Sm4Utils.decode(vo.getPhone()));
                    SetDevInfo(infoList,vo);
                }, executor);
                futures.add(future);
            }
            CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0])).join();
            executor.shutdown();
            return AjaxResult.success(list);

        }catch (Exception e){
            log.error(e.toString());
        }
        return AjaxResult.error("系统异常");
    }

    @Override
    public AjaxResult returnBoxBracelet(BoxEntity entity) {
         try{
            if(StringUtils.isEmpty(entity.getDevIds())){
                return AjaxResult.error("请选择归还的设备");
            }
            List<String> list= Arrays.asList(entity.getDevIds().split("@"));
            List<BoxEntity> boxList=mapper.getBoxBraceletNum(list);
             boxList.forEach(vo->{
                 if(vo.getShNum()>vo.getBoxNum()){
                     vo.setBoxNum(0);
                 }else {
                   int num= vo.getBoxNum()-vo.getShNum();
                     vo.setBoxNum(num);
                 }
                 mapper.updateBoxNum(vo);
             });
             AtomicInteger allNum= new AtomicInteger();
             list.forEach(devId->{
             int num=    mapper.updateBoxBraceletInfo(devId);
                 allNum.addAndGet(num);
             });
            if(list.size()==allNum.get()){
                return AjaxResult.success("归还成功");
            }
                 return AjaxResult.error("归还失败");
         }catch (Exception e){
             log.error(e.toString(),e);
         }
        return AjaxResult.error("系统异常");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addLsUser(MultipartFile file, String params) {
        try {
            if(ObjectUtils.isEmpty(file)){
                return AjaxResult.error("请上传人员图片");
            }
            LsUserEntity user= JSON.parseObject(params,LsUserEntity.class);

            if(StringUtils.isEmpty(user.getUserName())){
                return AjaxResult.error("用户名不能为空");
            }
            if(StringUtils.isEmpty(user.getIdCard())){
                return AjaxResult.error("身份证号码不能为空");
            }
            if(!IdCardUtil.isValidChineseID(user.getIdCard())){
                return AjaxResult.error("请填写正确的身份证号码");
            }
            if(StringUtils.isEmpty(user.getPhone())){
                return AjaxResult.error("手机号码不能为空");
            }
            if (!IdCardUtil.isValidChinaMobileNumber(user.getPhone())){
                return AjaxResult.error("请输入正确的手机号码");
            }
            String sex=IdCardUtil.getGenderByIdCard(user.getIdCard());
            user.setSex(sex);
            user.setPhone(Sm4Utils.encode(user.getPhone()));
            user.setIdCard(Sm4Utils.encode(user.getIdCard()));

            Integer num=mapper.getLsUserNum(user);
            if(num>0){
                return AjaxResult.error("临时人员已存在");
            }
            Integer num2=mapper.getPeopleNum(user);
            if(num2>0){
                return AjaxResult.error("该员工为正式员工");
            }
            LoginUser loginUser=  SecurityUtils.getLoginUser();
            mapper.insertLsUser(user);
            if(StringUtils.isNotEmpty(user.getId())){
              R result=fileService.singleUploadFile(file,SecurityConstants.INNER);

                if (result != null && result.getCode() == HttpStatus.ERROR) {
                    return AjaxResult.error("人员图片上传失败");
                } else if (result != null && result.getCode() == HttpStatus.SUCCESS && result.getData() != null) {
                    String jsonString = JSON.toJSONString(result.getData());
                    JSONObject item = JSON.parseObject(jsonString);
                    if (item != null) {
                        SysFileSource fileVo = setResourceFileData(item, user);
                        //添加图片到人脸库
                        R<Boolean> r=   sourceService.addFileSource(fileVo, SecurityConstants.INNER);
                          if(r.getData()){
                              AjaxResult ajaxResult = addFaceToLibrary(BytesToMultipartFileUtil.multipartFileToBase64(file), FaceCodeUtil.ADD, "rs-" + user.getId());
                              JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(ajaxResult.get("data")));
                              Integer code = data.getInteger("code");
                              String msg = data.getString("msg");
                              if (Objects.equals(code, BusinessConstants.SUCCESS_CODE)) {
                                  return AjaxResult.success("添加成功");
                              }else{
                                  throw new ServiceException(msg);
                              }
                          }
                    }
                }
            }
            return AjaxResult.error("添加失败");
        }catch (ServiceException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjaxResult.error(e.getMessage());
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error(e.toString(),e);
        }
        return AjaxResult.error("系统异常");
    }
    /**
     * 资源文件赋值
     *
     * @param item
     * @return ResourceFileVo
     * @author cwchen
     * @date 2024/7/16 13:49
     */
    public SysFileSource setResourceFileData(JSONObject item, LsUserEntity vo) {
        SysFileSource fileVo = new SysFileSource();
        fileVo.setFileType(1);
        fileVo.setFilePath(item.getString("fileId"));
        fileVo.setFileSuffix(item.getString("suffix"));
        fileVo.setFileName(item.getString("fileName"));
        fileVo.setSourceId(vo.getId());
        fileVo.setSourceType("6");
        return fileVo;
    }

    public AjaxResult addFaceToLibrary(String base64, String type, String id) {
        if (org.apache.commons.lang3.StringUtils.isEmpty(base64)) {
            return null;
        }
        AjaxResult ajaxResult = faceInterService.addFace(base64, type, id);
        log.info("添加人脸库返回结果：{}", ajaxResult);
        return ajaxResult;
    }

    /**
     * 赋值默认值
     * @param entity
     */
    public  void  setDefaultVal(BoxEntity entity){
        LoginUser loginUser=  SecurityUtils.getLoginUser();
    }
    /**
     * 比较距离
     * @param list
     * @param vo
     */
    public  void SetDevInfo( List<BraceletInfoEntity> list ,BraceletEntity vo){
                if(StringUtils.isNotEmpty(list)){
                    list.forEach(entity->{
                        if(StringHelper.isNotEmpty(entity.getDataVal())){
                            StringBuffer stringBuffer=new StringBuffer();
                            stringBuffer.append(entity.getDataVal());
                            if(StringUtils.isNotEmpty(entity.getDataUnit())){
                              //  stringBuffer.append("(");
                                stringBuffer.append(entity.getDataUnit());
                               // stringBuffer.append(")");
                            }
                            switch (entity.getDataCode()){
                                case  SystemConfig.dl_code:
                                    vo.setDl(stringBuffer.toString());
                                    break;
                                case  SystemConfig.lat_code:
                                    vo.setLat(stringBuffer.toString());
                                    break;
                                case  SystemConfig.lon_code:
                                    vo.setLon(stringBuffer.toString());
                                    break;
                                case  SystemConfig.xl_code:
                                    vo.setXl(stringBuffer.toString());
                                    break;
                                case  SystemConfig.xy_code:
                                    vo.setXy(stringBuffer.toString());
                                    break;
                                case  SystemConfig.wd_code:
                                    vo.setWd(stringBuffer.toString());
                                    break;
                            }
                        }
                        //查询人员高空作业证数量
                        int  gkNum=mapper.getCertificate(vo);
                        if(gkNum<1){
                            vo.setWarn("无高空作业证");
                        }

                    });
                }

    }

    /**
     * 查询施工范围
     * @param vo
     */
    public  void  setSgFw(BraceletEntity vo){
        int maxLne=getMaxLen();
        if(StringHelper.isNotEmpty(vo.getLat()) && StringHelper.isNotEmpty(vo.getLon())){
            if(StringHelper.isNotEmpty(vo.getSgLat()) && StringHelper.isNotEmpty(vo.getSgLon())){
                Double lat=Double.parseDouble(vo.getLat());
                Double lon=Double.parseDouble(vo.getLon());
                Double sgLat=Double.parseDouble(vo.getSgLat());
                Double sgLon=Double.parseDouble(vo.getSgLon());
                double len=HaversineUtil.vincentyDistance(sgLat,sgLon,lat,lon);
                if(len>maxLne){
                    vo.setSgFw("异常(超出作业范围)");

                }else{
                    vo.setSgFw("正常");
                }
            }
        }else{
            vo.setSgFw("无数据");
        }
    }


    /**
     * 获取施工范围默认值
     * @return
     */
    public int  getMaxLen(){
        List<SysDictData> dictDatas = DictUtils.getDictCache(SystemConfig.dict_code);
        int max_len=SystemConfig.max_len;
        try{
            if(StringUtils.isNotEmpty(dictDatas)){
                max_len=Integer.parseInt(dictDatas.get(0).getDictValue());
            }
        }catch (Exception e){
            log.error(e.toString(),e);
        }
        return  max_len;


    }
}
