package com.ruoyi.api.labour.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.api.base.TokenReqVo;
import com.ruoyi.api.labour.domain.LabourSignetVo;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.annotation.RateLimiter;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.HttpStatusEnum;
import com.ruoyi.common.enums.LimitType;
import com.ruoyi.common.enums.ShiFouEnum;
import com.ruoyi.common.enums.UserTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.AuthRsaUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.http.HttpClientUtil;
import com.ruoyi.common.utils.sign.Md5Utils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.system.domain.SysApplyConfig;
import com.ruoyi.system.service.ISysUserService;
import com.yanzhu.jh.project.domain.SurProjectAttendanceData;
import com.yanzhu.jh.project.domain.SurProjectAttendanceGroup;
import com.yanzhu.jh.project.domain.SurProjectAttendanceUser;
import com.yanzhu.jh.project.domain.vo.LabourDataVo;
import com.yanzhu.jh.project.domain.vo.LabourGroupVO;
import com.yanzhu.jh.project.domain.vo.LabourUserVO;
import com.yanzhu.jh.project.service.ISurProjectAttendanceDataService;
import com.yanzhu.jh.project.service.ISurProjectAttendanceGroupService;
import com.yanzhu.jh.project.service.ISurProjectAttendanceUserService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.Validation;
import java.util.*;

/**
 * 劳务人员APIController
 *
 * @author JiangYuQi
 * @date 2024-01-13
 */
@Slf4j
@RestController
@RequestMapping("/api/labour")
public class LabourApiController extends BaseController {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISurProjectAttendanceGroupService surProjectAttendanceGroupService;

    @Autowired
    private ISurProjectAttendanceUserService surProjectAttendanceUserService;

    @Autowired
    private ISurProjectAttendanceDataService surProjectAttendanceDataService;

    /**
     * 获取系统token
     * 限流规则[60秒内最多请求10次，限流策略IP]
     * @param req 请求信息
     * @author JiangYuQi
     * @date 2024-01-13
     */
    @Anonymous
    @ApiOperation(value = "获取TOKEN")
    @RateLimiter(count = 10, limitType = LimitType.IP)
    @PostMapping("/v1/getToken")
    public AjaxResult getToken(@Validated @RequestBody TokenReqVo req) {
        SysApplyConfig sysApplyConfig = redisCache.getCacheObject(CacheConstants.YANZHU_SYSTEM_CONFIG+req.getAppId());
        if(sysApplyConfig==null){
            throw new ServiceException(HttpStatusEnum.ERROR.getInfo(),HttpStatusEnum.ERROR.getCode());
        }
        if(StringUtils.equals(ShiFouEnum.SHI.getCode(),sysApplyConfig.getIsDel())){
            throw new ServiceException(HttpStatusEnum.DISABLE.getInfo(),HttpStatusEnum.DISABLE.getCode());
        }
        AjaxResult ajax = AjaxResult.success();
        String Authorization = "";
        if(!req.checkTimestamp()){
            throw new ServiceException(HttpStatusEnum.SINGET_TIMEOUT.getInfo(),HttpStatusEnum.SINGET_TIMEOUT.getCode());
        }
        if (req.getLoginSign(sysApplyConfig.getPrivateKey())) {
            Authorization = this.getAppIdLoginToken(req.getAppId(),sysApplyConfig);
        } else {
            throw new ServiceException(HttpStatusEnum.SINGET_ERROR.getInfo(),HttpStatusEnum.SINGET_ERROR.getCode());
        }
        ajax.put("Authorization", Authorization);
        return ajax;
    }

    /**
     * appId登录创建用户并模拟登录
     *
     * @param appId 用户账号
     * @return token
     */
    private String getAppIdLoginToken(String appId,SysApplyConfig sysApplyConfig) {
        // 查询用户是否存在，不存在则保存
        SysUser sysUser = userService.selectUserByUserName(appId);
        String password = Convert.toStr(System.currentTimeMillis());
        if (sysUser == null) {
            sysUser = new SysUser();
            sysUser.setDeptId(sysApplyConfig.getDeptId());
            sysUser.setUserName(Convert.toStr(sysApplyConfig.getAppId()));
            sysUser.setNickName(Convert.toStr(sysApplyConfig.getAppId()));
            sysUser.setUserType(UserTypeEnum.APPLY.getCode());
            sysUser.setStatus("0");
            sysUser.setCreateBy("AppId登录创建用户");
            sysUser.setPassword(SecurityUtils.encryptPassword(password));
            userService.insertUser(sysUser);
        } else {
            sysUser.setPassword(SecurityUtils.encryptPassword(password));
            sysUser.setUpdateBy("AppId登录更新用户密码");
            userService.updateUser(sysUser);
        }
        return loginService.unifiedLogin(appId, password);
    }

    /**
     * 推送,修改班组信息
     * 限流规则[30秒内最多请求100次，限流策略IP]
     * @param req 请求信息
     * @author JiangYuQi
     * @date 2024-01-13
     */
    @ApiOperation(value = "推送班组信息")
    @RateLimiter(time = 30, limitType = LimitType.IP)
    @PostMapping("/v1/pushLabourGroup")
    public AjaxResult pushLabourGroup(@Validated @RequestBody LabourSignetVo req) {
        SysApplyConfig sysApplyConfig = redisCache.getCacheObject(CacheConstants.YANZHU_SYSTEM_CONFIG+super.getUsername());
        if(StringUtils.equals(ShiFouEnum.SHI.getCode(),sysApplyConfig.getIsDel())){
            throw new ServiceException(HttpStatusEnum.DISABLE.getInfo(),HttpStatusEnum.DISABLE.getCode());
        }
        if(!req.checkTimestamp()){
            throw new ServiceException(HttpStatusEnum.SINGET_TIMEOUT.getInfo(),HttpStatusEnum.SINGET_TIMEOUT.getCode());
        }
        if(req.getDataSign(sysApplyConfig.getPrivateKey())){
            try {
                SurProjectAttendanceGroup surProjectAttendanceGroup =  JSONObject.parseObject(req.getData(), SurProjectAttendanceGroup.class);
                LabourGroupVO labourGroupVO = new LabourGroupVO();
                BeanUtils.copyBeanProp(labourGroupVO,surProjectAttendanceGroup);
                // 手动检测转换后的实体
                Set<ConstraintViolation<@Valid Object>> validateSet = Validation.buildDefaultValidatorFactory()
                        .getValidator()
                        .validate(labourGroupVO, new Class[0]);
                if(CollectionUtils.isEmpty(validateSet)){
                    // 查询当前班组是否已推送
                    SurProjectAttendanceGroup searchModel = new SurProjectAttendanceGroup();
                    searchModel.setAppId(sysApplyConfig.getAppId());
                    searchModel.setServerid(surProjectAttendanceGroup.getServerid());
                    List<SurProjectAttendanceGroup> list = surProjectAttendanceGroupService.selectSurProjectAttendanceGroupList(searchModel);
                    if(CollectionUtils.isNotEmpty(list)){
                        surProjectAttendanceGroup.setId(list.get(0).getId());
                        surProjectAttendanceGroup.setAppId(sysApplyConfig.getAppId());
                        surProjectAttendanceGroup.setCfgid(sysApplyConfig.getCfgId());
                        surProjectAttendanceGroup.setCreateBy(list.get(0).getCreateBy());
                        surProjectAttendanceGroup.setCreateTime(list.get(0).getCreateTime());
                        surProjectAttendanceGroup.setUpdateBy(sysApplyConfig.getAppId());
                        surProjectAttendanceGroupService.updateSurProjectAttendanceGroup(surProjectAttendanceGroup);
                    }else{
                        surProjectAttendanceGroup.setAppId(sysApplyConfig.getAppId());
                        surProjectAttendanceGroup.setCfgid(sysApplyConfig.getCfgId());
                        surProjectAttendanceGroup.setCreateBy(sysApplyConfig.getAppId());
                        surProjectAttendanceGroup.setCreateTime(new Date());
                        surProjectAttendanceGroupService.insertSurProjectAttendanceGroup(surProjectAttendanceGroup);
                    }
                }else{
                    String messages = validateSet.stream()
                            .map(ConstraintViolation::getMessage)
                            .reduce((m1, m2) -> m1 + "；" + m2)
                            .orElse("参数输入有误！");
                    throw new Exception(messages);
                }
            }catch (Exception e){
                throw new ServiceException(e.getMessage(),HttpStatusEnum.DARA_EXCEPTION.getCode());
            }
        }else{
            throw new ServiceException(HttpStatusEnum.SINGET_ERROR.getInfo(),HttpStatusEnum.SINGET_ERROR.getCode());
        }
        return success();
    }

    /**
     * 批量推送,修改班组列表信息
     * 限流规则[30秒内最多请求10次，限流策略IP]
     * @param req 请求信息
     * @author JiangYuQi
     * @date 2024-01-13
     */
    @ApiOperation(value = "推送班组列表信息")
    @RateLimiter(time = 30, count = 10, limitType = LimitType.IP)
    @PostMapping("/v1/pushLabourGroupList")
    public AjaxResult pushLabourGroupList(@Validated @RequestBody LabourSignetVo req) {
        SysApplyConfig sysApplyConfig = redisCache.getCacheObject(CacheConstants.YANZHU_SYSTEM_CONFIG+super.getUsername());
        if(StringUtils.equals(ShiFouEnum.SHI.getCode(),sysApplyConfig.getIsDel())){
            throw new ServiceException(HttpStatusEnum.DISABLE.getInfo(),HttpStatusEnum.DISABLE.getCode());
        }
        if(!req.checkTimestamp()){
            throw new ServiceException(HttpStatusEnum.SINGET_TIMEOUT.getInfo(),HttpStatusEnum.SINGET_TIMEOUT.getCode());
        }
        if(req.getDataSign(sysApplyConfig.getPrivateKey())){
            try {
                // 保存集合
                List<SurProjectAttendanceGroup> saveList = new ArrayList<>();
                List<SurProjectAttendanceGroup> surProjectAttendanceGroupList =  JSON.parseArray(req.getData(),SurProjectAttendanceGroup.class);
                if(CollectionUtils.isNotEmpty(surProjectAttendanceGroupList)){
                    for(int i=0;i<surProjectAttendanceGroupList.size();i++){
                        SurProjectAttendanceGroup surProjectAttendanceGroup = surProjectAttendanceGroupList.get(i);
                        LabourGroupVO labourGroupVO = new LabourGroupVO();
                        BeanUtils.copyBeanProp(labourGroupVO,surProjectAttendanceGroup);
                        // 手动检测转换后的实体
                        Set<ConstraintViolation<@Valid Object>> validateSet = Validation.buildDefaultValidatorFactory()
                                .getValidator()
                                .validate(labourGroupVO, new Class[0]);
                        if(CollectionUtils.isEmpty(validateSet)){
                            surProjectAttendanceGroup.setAppId(sysApplyConfig.getAppId());
                            surProjectAttendanceGroup.setCfgid(sysApplyConfig.getCfgId());
                            surProjectAttendanceGroup.setCreateBy(sysApplyConfig.getAppId());
                            surProjectAttendanceGroup.setCreateTime(new Date());
                            saveList.add(surProjectAttendanceGroup);
                        }else{
                            String messages = validateSet.stream()
                                    .map(ConstraintViolation::getMessage)
                                    .reduce((m1, m2) -> m1 + "；" + m2)
                                    .orElse("参数输入有误！");
                            throw new Exception("["+i+"]"+messages);
                        }
                    }
                    // 批量删除已保存数据
                    List<String> params = new ArrayList<>();
                    for(SurProjectAttendanceGroup surProjectAttendanceGroup:surProjectAttendanceGroupList){
                        params.add(sysApplyConfig.getAppId()+"-"+surProjectAttendanceGroup.getServerid());
                    }
                    surProjectAttendanceGroupService.deleteSurProjectAttendanceGroupByParams(params);
                    surProjectAttendanceGroupService.batchSurProjectAttendanceGroup(saveList);
                }
            }catch (Exception e){
                throw new ServiceException(e.getMessage(),HttpStatusEnum.DARA_EXCEPTION.getCode());
            }
        }else{
            throw new ServiceException(HttpStatusEnum.SINGET_ERROR.getInfo(),HttpStatusEnum.SINGET_ERROR.getCode());
        }
        return success();
    }

    /**
     * 推送,修改人员信息
     * 限流规则[30秒内最多请求100次，限流策略IP]
     * @param req 请求信息
     * @author JiangYuQi
     * @date 2024-01-13
     */
    @ApiOperation(value = "推送人员信息")
    @RateLimiter(time = 30, limitType = LimitType.IP)
    @PostMapping("/v1/pushLabourUser")
    public AjaxResult pushLabourUser(@Validated @RequestBody LabourSignetVo req) {
        SysApplyConfig sysApplyConfig = redisCache.getCacheObject(CacheConstants.YANZHU_SYSTEM_CONFIG+super.getUsername());
        if(StringUtils.equals(ShiFouEnum.SHI.getCode(),sysApplyConfig.getIsDel())){
            throw new ServiceException(HttpStatusEnum.DISABLE.getInfo(),HttpStatusEnum.DISABLE.getCode());
        }
        if(!req.checkTimestamp()){
            throw new ServiceException(HttpStatusEnum.SINGET_TIMEOUT.getInfo(),HttpStatusEnum.SINGET_TIMEOUT.getCode());
        }
        if(req.getDataSign(sysApplyConfig.getPrivateKey())){
            try {
                SurProjectAttendanceUser surProjectAttendanceUser =  JSONObject.parseObject(req.getData(), SurProjectAttendanceUser.class);
                LabourUserVO labourUserVO = new LabourUserVO();
                BeanUtils.copyBeanProp(labourUserVO,surProjectAttendanceUser);
                // 手动检测转换后的实体
                Set<ConstraintViolation<@Valid Object>> validateSet = Validation.buildDefaultValidatorFactory()
                        .getValidator()
                        .validate(labourUserVO, new Class[0]);
                if(CollectionUtils.isEmpty(validateSet)){
                    // 查询当前人员是否已推送
                    SurProjectAttendanceUser searchModel = new SurProjectAttendanceUser();
                    searchModel.setAppId(sysApplyConfig.getAppId());
                    searchModel.setWorkerId(surProjectAttendanceUser.getWorkerId());
                    List<SurProjectAttendanceUser> list = surProjectAttendanceUserService.selectSurProjectAttendanceUserList(searchModel);
                    if(CollectionUtils.isNotEmpty(list)){
                        surProjectAttendanceUser.setId(list.get(0).getId());
                        surProjectAttendanceUser.setCfgid(sysApplyConfig.getCfgId());
                        surProjectAttendanceUser.setAppId(sysApplyConfig.getAppId());
                        surProjectAttendanceUser.setCreateBy(list.get(0).getCreateBy());
                        surProjectAttendanceUser.setCreateTime(list.get(0).getCreateTime());
                        surProjectAttendanceUser.setUpdateBy(sysApplyConfig.getAppId());
                        surProjectAttendanceUserService.updateSurProjectAttendanceUser(surProjectAttendanceUser);
                    }else{
                        surProjectAttendanceUser.setAppId(sysApplyConfig.getAppId());
                        surProjectAttendanceUser.setCfgid(sysApplyConfig.getCfgId());
                        surProjectAttendanceUser.setCreateBy(sysApplyConfig.getAppId());
                        surProjectAttendanceUser.setCreateTime(new Date());
                        surProjectAttendanceUserService.insertSurProjectAttendanceUser(surProjectAttendanceUser);
                    }
                }else{
                    String messages = validateSet.stream()
                            .map(ConstraintViolation::getMessage)
                            .reduce((m1, m2) -> m1 + "；" + m2)
                            .orElse("参数输入有误！");
                    throw new Exception(messages);
                }
            }catch (Exception e){
                throw new ServiceException(e.getMessage(),HttpStatusEnum.DARA_EXCEPTION.getCode());
            }
        }else{
            throw new ServiceException(HttpStatusEnum.SINGET_ERROR.getInfo(),HttpStatusEnum.SINGET_ERROR.getCode());
        }
        return success();
    }

    /**
     * 批量推送,修改人员信息
     * 限流规则[30秒内最多请求10次，限流策略IP]
     * @param req 请求信息
     * @author JiangYuQi
     * @date 2024-01-13
     */
    @ApiOperation(value = "推送人员信息")
    @RateLimiter(time = 30, count = 10, limitType = LimitType.IP)
    @PostMapping("/v1/pushLabourUserList")
    public AjaxResult pushLabourUserList(@Validated @RequestBody LabourSignetVo req) {
        SysApplyConfig sysApplyConfig = redisCache.getCacheObject(CacheConstants.YANZHU_SYSTEM_CONFIG+super.getUsername());
        if(StringUtils.equals(ShiFouEnum.SHI.getCode(),sysApplyConfig.getIsDel())){
            throw new ServiceException(HttpStatusEnum.DISABLE.getInfo(),HttpStatusEnum.DISABLE.getCode());
        }
        if(!req.checkTimestamp()){
            throw new ServiceException(HttpStatusEnum.SINGET_TIMEOUT.getInfo(),HttpStatusEnum.SINGET_TIMEOUT.getCode());
        }
        if(req.getDataSign(sysApplyConfig.getPrivateKey())){
            try {
                // 保存集合
                List<SurProjectAttendanceUser> saveList = new ArrayList<>();
                List<SurProjectAttendanceUser> surProjectAttendanceUserList =  JSON.parseArray(req.getData(),SurProjectAttendanceUser.class);
                if(CollectionUtils.isNotEmpty(surProjectAttendanceUserList)){
                    for(int i=0;i<surProjectAttendanceUserList.size();i++){
                        SurProjectAttendanceUser surProjectAttendanceUser = surProjectAttendanceUserList.get(i);
                        LabourUserVO labourUserVO = new LabourUserVO();
                        BeanUtils.copyBeanProp(labourUserVO,surProjectAttendanceUser);
                        // 手动检测转换后的实体
                        Set<ConstraintViolation<@Valid Object>> validateSet = Validation.buildDefaultValidatorFactory()
                                .getValidator()
                                .validate(labourUserVO, new Class[0]);
                        if(CollectionUtils.isEmpty(validateSet)){
                            surProjectAttendanceUser.setCfgid(sysApplyConfig.getCfgId());
                            surProjectAttendanceUser.setCreateBy(sysApplyConfig.getAppId());
                            surProjectAttendanceUser.setCreateTime(new Date());
                            saveList.add(surProjectAttendanceUser);
                        }else{
                            String messages = validateSet.stream()
                                    .map(ConstraintViolation::getMessage)
                                    .reduce((m1, m2) -> m1 + "；" + m2)
                                    .orElse("参数输入有误！");
                            throw new Exception("["+i+"]"+messages);
                        }
                    }
                    // 批量删除已保存数据
                    List<String> params = new ArrayList<>();
                    for(SurProjectAttendanceUser surProjectAttendanceUser:surProjectAttendanceUserList){
                        params.add(sysApplyConfig.getAppId()+"-"+surProjectAttendanceUser.getWorkerId());
                    }
                    //删除后新增
                    surProjectAttendanceUserService.deleteSurProjectAttendanceUserByParams(params);
                    surProjectAttendanceUserService.batchSurProjectAttendanceUser(saveList);
                }
            }catch (Exception e){
                throw new ServiceException(e.getMessage(),HttpStatusEnum.DARA_EXCEPTION.getCode());
            }
        }else{
            throw new ServiceException(HttpStatusEnum.SINGET_ERROR.getInfo(),HttpStatusEnum.SINGET_ERROR.getCode());
        }
        return success();
    }

    /**
     * 推送,修改班组人员考勤信息
     * 限流规则[30秒内最多请求255次，限流策略IP]
     * @param req 请求信息
     * @author JiangYuQi
     * @date 2024-01-13
     */
    @ApiOperation(value = "推送班组人员考勤信息")
    @RateLimiter(time = 30, count = 255, limitType = LimitType.IP)
    @PostMapping("/v1/pushLabourData")
    public AjaxResult pushLabourData(@Validated @RequestBody LabourSignetVo req) {
        SysApplyConfig sysApplyConfig = redisCache.getCacheObject(CacheConstants.YANZHU_SYSTEM_CONFIG+super.getUsername());
        if(StringUtils.equals(ShiFouEnum.SHI.getCode(),sysApplyConfig.getIsDel())){
            throw new ServiceException(HttpStatusEnum.DISABLE.getInfo(),HttpStatusEnum.DISABLE.getCode());
        }
        if(!req.checkTimestamp()){
            throw new ServiceException(HttpStatusEnum.SINGET_TIMEOUT.getInfo(),HttpStatusEnum.SINGET_TIMEOUT.getCode());
        }
        if(req.getDataSign(sysApplyConfig.getPrivateKey())){
            try {
                SurProjectAttendanceData surProjectAttendanceData =  JSONObject.parseObject(req.getData(), SurProjectAttendanceData.class);
                LabourDataVo labourDataVo = new LabourDataVo();
                BeanUtils.copyBeanProp(labourDataVo,surProjectAttendanceData);
                // 手动检测转换后的实体
                Set<ConstraintViolation<@Valid Object>> validateSet = Validation.buildDefaultValidatorFactory()
                        .getValidator()
                        .validate(labourDataVo, new Class[0]);
                if(CollectionUtils.isEmpty(validateSet)){
                    // 查询当前班组人员考勤是否已推送
                    SurProjectAttendanceData findData = new SurProjectAttendanceData();
                    findData.setAppId(sysApplyConfig.getAppId());
                    findData.setWorkerId(surProjectAttendanceData.getWorkerId());
                    findData.setAttendanceTime(labourDataVo.getAttendanceTime());
                    SurProjectAttendanceData data = surProjectAttendanceDataService.findCurrentAttendanceData(findData);
                    if(data!=null){
                        //这里不能修改出勤时间
                        surProjectAttendanceData.setAttendanceTime(null);
                        surProjectAttendanceData.setAttendanceOutTime(labourDataVo.getAttendanceTime());
                        surProjectAttendanceData.setUpdateBy(sysApplyConfig.getAppId()+"Api推送离场");
                        surProjectAttendanceData.setUpdateTime(new Date());
                        surProjectAttendanceDataService.updateSurProjectAttendanceData(surProjectAttendanceData);
                    }else{
                        /**
                         * 查询人员考勤信息
                         */
                        SurProjectAttendanceUser findUser = new SurProjectAttendanceUser();
                        findUser.setCfgid(sysApplyConfig.getCfgId());
                        findUser.setWorkerId(surProjectAttendanceData.getWorkerId());
                        SurProjectAttendanceUser surProjectAttendanceUser = surProjectAttendanceUserService.findCurrentAttendanceUser(findUser);
                        if(StringUtils.isNull(surProjectAttendanceUser)){
                            throw new ServiceException("未查询到人员信息",HttpStatusEnum.DARA_EXCEPTION.getCode());
                        }
                        if(StringUtils.isNull(surProjectAttendanceUser.getCompanyTypeId())){
                            throw new ServiceException("人员部门类型信息不完整",HttpStatusEnum.DARA_EXCEPTION.getCode());
                        }
                        surProjectAttendanceData.setAppId(sysApplyConfig.getAppId());
                        surProjectAttendanceData.setCfgid(sysApplyConfig.getCfgId());
                        surProjectAttendanceData.setCompanyId(surProjectAttendanceUser.getCompanyId());
                        surProjectAttendanceData.setCompanyName(surProjectAttendanceUser.getCompanyName());
                        surProjectAttendanceData.setWorkerName(surProjectAttendanceUser.getName());
                        surProjectAttendanceData.setWorkerPhoto(surProjectAttendanceUser.getRecentPhoto());
                        surProjectAttendanceData.setWorkerGender(surProjectAttendanceUser.getGender());
                        surProjectAttendanceData.setBirthDate(surProjectAttendanceUser.getBirthDate());
                        surProjectAttendanceData.setEthnic(surProjectAttendanceUser.getEthnic());
                        surProjectAttendanceData.setNativePlace(surProjectAttendanceUser.getNativePlace());
                        surProjectAttendanceData.setPhone(surProjectAttendanceUser.getPhone());
                        surProjectAttendanceData.setWorkTypeName(surProjectAttendanceUser.getWorkTypeName());
                        surProjectAttendanceData.setSpecWorkType(surProjectAttendanceUser.getSpecWorkType());
                        surProjectAttendanceData.setGroupName(surProjectAttendanceUser.getGroupName());
                        surProjectAttendanceData.setCompanyTypeId(surProjectAttendanceUser.getCompanyTypeId());
                        surProjectAttendanceData.setWorkTypeCode(surProjectAttendanceUser.getWorkTypeCode());
                        surProjectAttendanceData.setCreateBy(sysApplyConfig.getAppId()+"Api推送入场");
                        surProjectAttendanceData.setCreateTime(new Date());
                        List<SurProjectAttendanceData> list = new ArrayList<>();
                        list.add(surProjectAttendanceData);
                        surProjectAttendanceDataService.batchSurProjectAttendanceData(list);
                    }
                }else{
                    String messages = validateSet.stream()
                            .map(ConstraintViolation::getMessage)
                            .reduce((m1, m2) -> m1 + "；" + m2)
                            .orElse("参数输入有误！");
                    throw new Exception(messages);
                }
            }catch (Exception e){
                log.error(e.getMessage());
                throw new ServiceException(e.getMessage(),HttpStatusEnum.DARA_EXCEPTION.getCode());
            }
        }else{
            throw new ServiceException(HttpStatusEnum.SINGET_ERROR.getInfo(),HttpStatusEnum.SINGET_ERROR.getCode());
        }
        return success();
    }

    /**
     * 批量推送,修改班组人员考勤信息
     * 限流规则[30秒内最多请求10次，限流策略IP]
     * @param req 请求信息
     * @author JiangYuQi
     * @date 2024-01-13
     */
    @ApiOperation(value = "推送班组人员考勤信息")
    @RateLimiter(time = 30, count = 10, limitType = LimitType.IP)
    @PostMapping("/v1/pushLabourDataList")
    public AjaxResult pushLabourDataList(@Validated @RequestBody LabourSignetVo req) {
        SysApplyConfig sysApplyConfig = redisCache.getCacheObject(CacheConstants.YANZHU_SYSTEM_CONFIG+super.getUsername());
        if(StringUtils.equals(ShiFouEnum.SHI.getCode(),sysApplyConfig.getIsDel())){
            throw new ServiceException(HttpStatusEnum.DISABLE.getInfo(),HttpStatusEnum.DISABLE.getCode());
        }
        if(!req.checkTimestamp()){
            throw new ServiceException(HttpStatusEnum.SINGET_TIMEOUT.getInfo(),HttpStatusEnum.SINGET_TIMEOUT.getCode());
        }
        if(req.getDataSign(sysApplyConfig.getPrivateKey())){
            try {
                // 保存集合
                List<SurProjectAttendanceData> saveList = new ArrayList<>();
                List<SurProjectAttendanceData> surProjectAttendanceDataList =  JSON.parseArray(req.getData(),SurProjectAttendanceData.class);
                if(CollectionUtils.isNotEmpty(surProjectAttendanceDataList)){
                    for(int i=0;i<surProjectAttendanceDataList.size();i++){
                        SurProjectAttendanceData surProjectAttendanceData = surProjectAttendanceDataList.get(i);
                        LabourDataVo labourDataVo = new LabourDataVo();
                        BeanUtils.copyBeanProp(labourDataVo,surProjectAttendanceData);
                        // 手动检测转换后的实体
                        Set<ConstraintViolation<@Valid Object>> validateSet = Validation.buildDefaultValidatorFactory()
                                .getValidator()
                                .validate(labourDataVo, new Class[0]);
                        if(CollectionUtils.isEmpty(validateSet)){
                            surProjectAttendanceData.setAppId(sysApplyConfig.getAppId());
                            surProjectAttendanceData.setCfgid(sysApplyConfig.getCfgId());
                            surProjectAttendanceData.setCreateBy(sysApplyConfig.getAppId());
                            surProjectAttendanceData.setCreateTime(new Date());
                            saveList.add(surProjectAttendanceData);
                        }else{
                            String messages = validateSet.stream()
                                    .map(ConstraintViolation::getMessage)
                                    .reduce((m1, m2) -> m1 + "；" + m2)
                                    .orElse("参数输入有误！");
                            throw new Exception("["+i+"]"+messages);
                        }
                    }
                    for(SurProjectAttendanceData surProjectAttendanceData:surProjectAttendanceDataList){
                        // 查询当前班组人员考勤是否已推送
                        SurProjectAttendanceData findData = new SurProjectAttendanceData();
                        findData.setAppId(sysApplyConfig.getAppId());
                        findData.setWorkerId(surProjectAttendanceData.getWorkerId());
                        findData.setAttendanceTime(surProjectAttendanceData.getAttendanceTime());
                        SurProjectAttendanceData data = surProjectAttendanceDataService.findCurrentAttendanceData(findData);
                        if(data!=null){
                            //这里不能修改出勤时间
                            surProjectAttendanceData.setAttendanceTime(null);
                            surProjectAttendanceData.setAttendanceOutTime(surProjectAttendanceData.getAttendanceTime());
                            surProjectAttendanceData.setUpdateBy(sysApplyConfig.getAppId()+"Api推送离场");
                            surProjectAttendanceData.setUpdateTime(new Date());
                            surProjectAttendanceDataService.updateSurProjectAttendanceData(surProjectAttendanceData);
                        }else{
                            /**
                             * 查询人员考勤信息
                             */
                            SurProjectAttendanceUser findUser = new SurProjectAttendanceUser();
                            findUser.setCfgid(sysApplyConfig.getCfgId());
                            findUser.setWorkerId(surProjectAttendanceData.getWorkerId());
                            SurProjectAttendanceUser surProjectAttendanceUser = surProjectAttendanceUserService.findCurrentAttendanceUser(findUser);
                            if(StringUtils.isNull(surProjectAttendanceUser)){
                                throw new ServiceException("未查询到人员信息",HttpStatusEnum.DARA_EXCEPTION.getCode());
                            }
                            if(StringUtils.isNull(surProjectAttendanceUser.getCompanyTypeId())){
                                throw new ServiceException("人员部门类型信息不完整",HttpStatusEnum.DARA_EXCEPTION.getCode());
                            }
                            surProjectAttendanceData.setAppId(sysApplyConfig.getAppId());
                            surProjectAttendanceData.setCfgid(sysApplyConfig.getCfgId());
                            surProjectAttendanceData.setCompanyId(surProjectAttendanceUser.getCompanyId());
                            surProjectAttendanceData.setCompanyName(surProjectAttendanceUser.getCompanyName());
                            surProjectAttendanceData.setWorkerName(surProjectAttendanceUser.getName());
                            surProjectAttendanceData.setWorkerPhoto(surProjectAttendanceUser.getRecentPhoto());
                            surProjectAttendanceData.setWorkerGender(surProjectAttendanceUser.getGender());
                            surProjectAttendanceData.setBirthDate(surProjectAttendanceUser.getBirthDate());
                            surProjectAttendanceData.setEthnic(surProjectAttendanceUser.getEthnic());
                            surProjectAttendanceData.setNativePlace(surProjectAttendanceUser.getNativePlace());
                            surProjectAttendanceData.setPhone(surProjectAttendanceUser.getPhone());
                            surProjectAttendanceData.setWorkTypeName(surProjectAttendanceUser.getWorkTypeName());
                            surProjectAttendanceData.setSpecWorkType(surProjectAttendanceUser.getSpecWorkType());
                            surProjectAttendanceData.setGroupName(surProjectAttendanceUser.getGroupName());
                            surProjectAttendanceData.setCompanyTypeId(surProjectAttendanceUser.getCompanyTypeId());
                            surProjectAttendanceData.setWorkTypeCode(surProjectAttendanceUser.getWorkTypeCode());
                            surProjectAttendanceData.setCreateBy(sysApplyConfig.getAppId()+"Api推送入场");
                            surProjectAttendanceData.setCreateTime(new Date());
                            saveList.add(surProjectAttendanceData);
                        }
                    }
                    if(StringUtils.isNotEmpty(saveList)){
                        surProjectAttendanceDataService.batchSurProjectAttendanceData(saveList);
                    }
                }
            }catch (Exception e){
                throw new ServiceException(e.getMessage(),HttpStatusEnum.DARA_EXCEPTION.getCode());
            }
        }else{
            throw new ServiceException(HttpStatusEnum.SINGET_ERROR.getInfo(),HttpStatusEnum.SINGET_ERROR.getCode());
        }
        return success();
    }

    private static final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCZjinQdEjtWt+4EiXIa/xVz4pfcOPYzZUMCAh1xXG9+2j6Wb++XoajlgVxjL/XkK3CnZh9PjrUxWpnQKEVt+QyIS1O0yCiZjMzaQ4sHoMs4uPYh8fyYAuL4uF/6R2x0/PL460quC1aMTmdSdXWLlIiwk5ZRm7YB/k1Nb/P91MKwIDAQAB";
    private static final String baseUrl = "https://szgc.jhncidg.com/jhapi";
    private static final String token = "eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImYyZmUzYTFhLWI2NDQtNGVmZC05NTZiLTYyMDk3Y2I5M2JmNSJ9.B_Rszwgn_pE3cZDNyjY9Di6BVxzslJYlBVmpo-6IiG4LJst4o0-WvSE3lRgamMr006Ey_L04SBlildae8PH4BQ";

    /**
     * 推送,修改班组信息【示例代码】
     */
    public static String getToken(){
        String timestamp = String.valueOf(System.currentTimeMillis());
        String appId = "jhcf170515993052073qrDFKJmk001";
        try {
            // 明文信息->公钥加密
            String encryptByPublicKeyStr = AuthRsaUtils.encryptByPublicKey(publicKey, appId+timestamp);
            log.info("公钥加密...{}" , encryptByPublicKeyStr);
            // redis中查询->未查询到则重新获取
            String url = baseUrl + "/api/labour/v1/getToken";
            Map<String, Object> body = new HashMap<>();
            body.put("appId",appId);
            body.put("sign",encryptByPublicKeyStr);
            body.put("timestamp",timestamp);
            String result = HttpClientUtil.doPost(url, null, com.alibaba.fastjson2.JSON.toJSONString(body));
            JSONObject jsonObject = JSONObject.parseObject(result);
            if(jsonObject.getInteger("code")==200){
                // 获取到存入redis，设置30分钟有效期
                String token = jsonObject.getString("Authorization");
                log.info("Authorization...{}" , token);
                return token;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 推送,修改班组信息【示例代码】
     */
    public static void pushLabourGroup(){
        Map<String,Object> map = new HashMap<>();
        map.put("serverid","5013720");
        map.put("companyId",5002894);
        map.put("companyCode","91361122553504962W");
        map.put("companyName","江西省子金建设工程有限公司");
        map.put("companyTypeId","2");
        map.put("name","江西子金管理");
        map.put("isDel",1);
        String jsonString = JSONObject.toJSONString(map);
        String timestamp = "1705915778869";//String.valueOf(System.currentTimeMillis());
        try {
            // 明文信息->公钥加密
            String encryptByPublicKeyStr = AuthRsaUtils.encryptByPublicKey(publicKey, Md5Utils.hash(jsonString)+timestamp);
            log.info("公钥加密...{}" , encryptByPublicKeyStr);
            String url = baseUrl + "/api/labour/v1/pushLabourGroup";
            Map<String, Object> body = new HashMap<>();
            body.put("sign",encryptByPublicKeyStr);
            body.put("data",jsonString);
            body.put("timestamp",timestamp);
            // redis中查询->未查询到则重新获取
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", token);
            String result = HttpClientUtil.doPost(url, headers, com.alibaba.fastjson2.JSON.toJSONString(body));
            JSONObject jsonObject = JSONObject.parseObject(result);
            if(jsonObject.getInteger("code")==200){
                log.info("success...{}");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 批量推送班组信息【示例代码】
     */
    public static void pushLabourGroupList(List<Map<String,Object>> datas){
        Map<String,Object> map = new HashMap<>();
        map.put("serverid","1");
        map.put("companyId",123);
        map.put("companyName","1222222222222222222222222");
        map.put("companyTypeId","1");
        map.put("name","12");
        map.put("isDel",1);
        datas.add(map);
        Map<String,Object> map1 = new HashMap<>();
        map1.put("serverid","1");
        map1.put("companyId",123);
        map1.put("companyName","1222222222222222222222222");
        map1.put("companyTypeId","1");
        map1.put("name","12");
        map1.put("isDel",1);
        datas.add(map1);
        String jsonString = JSONObject.toJSONString(datas);
        String timestamp = String.valueOf(System.currentTimeMillis());
        try {
            // 明文信息->公钥加密
            String encryptByPublicKeyStr = AuthRsaUtils.encryptByPublicKey(publicKey, Md5Utils.hash(jsonString)+timestamp);
            log.info("公钥加密...{}" , encryptByPublicKeyStr);
            String url = baseUrl + "/api/labour/v1/pushLabourGroupList";
            Map<String, Object> body = new HashMap<>();
            body.put("sign",encryptByPublicKeyStr);
            body.put("data",jsonString);
            body.put("timestamp",timestamp);
            // redis中查询->未查询到则重新获取
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", token);
            String result = HttpClientUtil.doPost(url, headers, com.alibaba.fastjson2.JSON.toJSONString(body));
            JSONObject jsonObject = JSONObject.parseObject(result);
            if(jsonObject.getInteger("code")==200){
                JSONArray jsonArray = jsonObject.getJSONArray("data");
                log.info("推送失败下标...{}",jsonArray);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 推送,修改人员信息【示例代码】
     */
    public static void pushLabourUser(){
        Map<String,Object> map = new HashMap<>();
        map.put("workerId","1");
        map.put("name","张三");
        map.put("phone","张三");
        map.put("groupId",1);
        map.put("companyId",1);
        map.put("groupName","张三112");
        map.put("workTypeName","张三112");
        map.put("specWorkType",1);
        map.put("typeName",1);
        map.put("ethnic","1213");
        map.put("gender",1);
        map.put("recentPhoto","http:///api/labour/v1/pushLabourUser/123");
        map.put("nativePlace","张三111");
        map.put("enterDate",1);
        map.put("state",1);
        map.put("isDel",1);
        String jsonString = JSONObject.toJSONString(map);
        String timestamp = String.valueOf(System.currentTimeMillis());
        try {
            String s = Md5Utils.hash(jsonString)+timestamp;
            log.info("签名明文...{}" , s);
            // 明文信息->公钥加密
            String encryptByPublicKeyStr = AuthRsaUtils.encryptByPublicKey(publicKey, s);
            log.info("公钥加密...{}" , encryptByPublicKeyStr);
            String url = baseUrl + "/api/labour/v1/pushLabourUser";
            Map<String, Object> body = new HashMap<>();
            body.put("sign",encryptByPublicKeyStr);
            body.put("data",jsonString);
            body.put("timestamp",timestamp);
            // redis中查询->未查询到则重新获取
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", token);
            String result = HttpClientUtil.doPost(url, headers, com.alibaba.fastjson2.JSON.toJSONString(body));
            JSONObject jsonObject = JSONObject.parseObject(result);
            if(jsonObject.getInteger("code")==200){
                log.info("success...{}");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 批量推送人员信息【示例代码】
     */
    public static void pushLabourUserList(List<Map<String,Object>> datas){
        Map<String,Object> map = new HashMap<>();
        map.put("workerId","1");
        map.put("name","张三");
        map.put("phone","张三");
        map.put("groupId",1);
        map.put("companyId",1);
        map.put("groupName","张三112");
        map.put("workTypeName","张三112");
        map.put("specWorkType",1);
        map.put("typeName",1);
        map.put("ethnic","1213");
        map.put("gender",1);
        map.put("recentPhoto","http:///api/labour/v1/pushLabourUser/123");
        map.put("nativePlace","张三111");
        map.put("enterDate",1);
        map.put("state",1);
        map.put("isDel",1);
        datas.add(map);
        Map<String,Object> map1 = new HashMap<>();
        map1.put("workerId","1");
        map1.put("name","张三");
        map1.put("phone","张三");
        map1.put("groupId",1);
        map1.put("companyId",1);
        map1.put("groupName","张三112");
        map1.put("workTypeName","张三112");
        map1.put("specWorkType",1);
        map1.put("typeName",1);
        map1.put("ethnic","1213");
        map1.put("gender",1);
        map1.put("recentPhoto","http:///api/labour/v1/pushLabourUser/123");
        map1.put("nativePlace","张三111");
        map1.put("enterDate",1);
        map1.put("state",1);
        map1.put("isDel",1);
        datas.add(map1);
        String jsonString = JSONObject.toJSONString(datas);
        String timestamp = String.valueOf(System.currentTimeMillis());
        try {
            // 明文信息->公钥加密
            String encryptByPublicKeyStr = AuthRsaUtils.encryptByPublicKey(publicKey, Md5Utils.hash(jsonString)+timestamp);
            log.info("公钥加密...{}" , encryptByPublicKeyStr);
            String url = baseUrl + "/api/labour/v1/pushLabourUserList";
            Map<String, Object> body = new HashMap<>();
            body.put("sign",encryptByPublicKeyStr);
            body.put("data",jsonString);
            body.put("timestamp",timestamp);
            // redis中查询->未查询到则重新获取
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", token);
            String result = HttpClientUtil.doPost(url, headers, com.alibaba.fastjson2.JSON.toJSONString(body));
            JSONObject jsonObject = JSONObject.parseObject(result);
            if(jsonObject.getInteger("code")==200){
                JSONArray jsonArray = jsonObject.getJSONArray("data");
                log.info("推送失败下标...{}",jsonArray);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 推送,修改班组人员出勤信息【示例代码】
     */
    public static void pushLabourData(){
        Map<String,Object> map = new HashMap<>();
        map.put("serverid","1");
        map.put("workerId","1");
        map.put("companyId",1);
        map.put("attendanceType","E");
        map.put("attendanceTime","2022-11-22 11:11:11");
        map.put("identification","11231231232132");
        map.put("isDel",1);
        String jsonString = JSONObject.toJSONString(map);
        String timestamp = String.valueOf(System.currentTimeMillis());
        try {
            // 明文信息->公钥加密
            String encryptByPublicKeyStr = AuthRsaUtils.encryptByPublicKey(publicKey, Md5Utils.hash(jsonString)+timestamp);
            log.info("公钥加密...{}" , encryptByPublicKeyStr);
            String url = baseUrl + "/api/labour/v1/pushLabourData";
            Map<String, Object> body = new HashMap<>();
            body.put("sign",encryptByPublicKeyStr);
            body.put("data",jsonString);
            body.put("timestamp",timestamp);
            // redis中查询->未查询到则重新获取
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", token);
            String result = HttpClientUtil.doPost(url, headers, com.alibaba.fastjson2.JSON.toJSONString(body));
            JSONObject jsonObject = JSONObject.parseObject(result);
            if(jsonObject.getInteger("code")==200){
                log.info("success...{}");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 批量推送班组人员出勤信息【示例代码】
     */
    public static void pushLabourDataList(List<Map<String,Object>> datas){
        Map<String,Object> map = new HashMap<>();
        map.put("serverid","1");
        map.put("workerId","1");
        map.put("companyId",1);
        map.put("attendanceType","E");
        map.put("attendanceTime","2022-11-22 11:11:11");
        map.put("identification","11231231232132");
        map.put("isDel",1);
        datas.add(map);
        Map<String,Object> map1 = new HashMap<>();
        map1.put("serverid","1");
        map1.put("workerId","1");
        map1.put("companyId",1);
        map1.put("attendanceType","E");
        map1.put("attendanceTime","2022-11-22 11:11:11");
        map1.put("identification","11231231232132");
        map1.put("isDel",1);
        datas.add(map1);
        String jsonString = JSONObject.toJSONString(datas);
        String timestamp = String.valueOf(System.currentTimeMillis());
        try {
            // 明文信息->公钥加密
            String s = Md5Utils.hash(jsonString)+timestamp;
            log.info("签名明文...{}" , s);
            String encryptByPublicKeyStr = AuthRsaUtils.encryptByPublicKey(publicKey, s);
            log.info("公钥加密...{}" , encryptByPublicKeyStr);
            String url = baseUrl + "/api/labour/v1/pushLabourDataList";
            Map<String, Object> body = new HashMap<>();
            body.put("sign",encryptByPublicKeyStr);
            body.put("data",jsonString);
            body.put("timestamp",timestamp);
            // redis中查询->未查询到则重新获取
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", token);
            String result = HttpClientUtil.doPost(url, headers, com.alibaba.fastjson2.JSON.toJSONString(body));
            JSONObject jsonObject = JSONObject.parseObject(result);
            if(jsonObject.getInteger("code")==200){
                JSONArray jsonArray = jsonObject.getJSONArray("data");
                log.info("推送失败下标...{}",jsonArray);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        String baseUrl = "https://szgc.jhncidg.com/jhapi";
        String timestamp = String.valueOf(System.currentTimeMillis());
        String appId = "jhcf17054840354615gUkkFJvTn003";
        try {
            // 明文信息->公钥加密
            String encryptByPublicKeyStr = AuthRsaUtils.encryptByPublicKey(publicKey, appId+timestamp);
            log.info("公钥加密...{}" , encryptByPublicKeyStr);
            // redis中查询->未查询到则重新获取
            String url = baseUrl + "/api/labour/v1/getToken";
            Map<String, Object> body = new HashMap<>();
            body.put("appId",appId);
            body.put("sign",encryptByPublicKeyStr);
            body.put("timestamp",timestamp);
            String result = HttpClientUtil.doPost(url, null, com.alibaba.fastjson2.JSON.toJSONString(body));
            JSONObject jsonObject = JSONObject.parseObject(result);
            if(jsonObject.getInteger("code")==200){
                // 获取到存入redis，设置30分钟有效期
                String token = jsonObject.getString("Authorization");
                log.info("Authorization...{}" , token);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}
