package com.bonus.system.att.tasks;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.bonus.common.core.utils.FastJsonHelper;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.encryption.AESCBCUtil;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.att.dao.WechatPushDao;
import com.bonus.system.att.entity.AttFaceBean;
import com.bonus.system.att.entity.AttSourceDataBean;
import com.bonus.system.att.utils.DistanceCalculator;
import com.bonus.system.att.utils.IpAndPathConfig;
import com.bonus.system.basic.domain.SysOrg;
import com.bonus.system.evection.entity.EvectionBean;
import com.bonus.system.index.entity.MapBean;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static com.bonus.system.att.utils.DistanceCalculator.calculateDistance;

/**
 * @author fly
 * 微信小程序数据同步接口
 */
@Configuration
@Slf4j
@EnableScheduling
@EnableAsync
public class WechatTasks {

    @Resource(name = "WechatPushDao")
    private WechatPushDao dao;

    private String token;

    private int index = 4;

    /**
     * 人员基础数据同步定时器
     */
//        @Scheduled(cron = "0 0/10 * * * ?")
    @Scheduled(initialDelay = 60000,fixedDelay = 60000 * 30)
    @Async
    public void pushPersonTask() {
        log.info("--------人员基础数据同步定时器开启------");
        index=4;

        //人脸更新
        List<AttFaceBean> faceList = dao.getWebFaceList();
        String jsonStr2 = "{}";
        String method2 = "getWeChatFaceList";
        String string2 = httpPost(method2, jsonStr2);
        List<AttFaceBean> wechatFaceList = FastJsonHelper.jsonArrStrToBeanList(string2, AttFaceBean.class);
        syncFaceToDatabase(faceList, wechatFaceList);

        //考勤库人员
        List<SysUser> list = dao.getPersonList();
        //考勤小程序库人员
        String jsonStr = "{}";
        String method = "getWeChatPersonList";
        String string = httpPost(method, jsonStr);
        List<SysUser> wechatList = FastJsonHelper.jsonArrStrToBeanList(string, SysUser.class);
//        //所有字段同步
        syncListsToDatabase(list, wechatList);

        log.info("--------人员基础数据同步定时器完毕------");
    }

    /**
     * 休假出差数据同步定时器
     */
    @Scheduled(initialDelay = 60000 * 2,fixedDelay = 60000 * 30)
    @Async
    public void leaveTask() {
        log.info("--------休假出差数据定时器开启------");
        index=4;
        //小程序库人员
        String jsonStr = "{}";
        String method = "getWechatLeaveList";
        String string = httpPost(method, jsonStr);
        List<EvectionBean> list = FastJsonHelper.jsonArrStrToBeanList(string, EvectionBean.class);
        //将所有人数据更新组织机构
        for (EvectionBean bean : list) {
            if(bean.getId() != 0L){
                continue;
            }
            // 如果Map中没有该userId的组织机构信息，则从数据库查询
            SysOrg orgInfo = dao.getOrgInfoByUserId(bean.getUserId());
            if (orgInfo != null) {
                bean.setOrgId(orgInfo.getId());
                bean.setOrgName(orgInfo.getOrgName());
            }
            dao.insertWebLeave(bean);
            String jsonStr2 = FastJsonHelper.beanToJsonStr(bean);
            String method2 = "updateWechatLeave";
            String string2 = httpPost(method2, jsonStr2);
        }
        //在将所有数据同步过去
        List<EvectionBean> webList = dao.getWebLeaveList();
        String jsonStr2 = "{}";
        String method2 = "getWechatLeaveList";
        String string2 = httpPost(method2, jsonStr2);
        List<EvectionBean> webchatList = FastJsonHelper.jsonArrStrToBeanList(string2, EvectionBean.class);
        syncLeaveToDatabase(webList,webchatList);
        log.info("--------休假出差数据定时器完毕------");
    }

    private void syncLeaveToDatabase(List<EvectionBean> list, List<EvectionBean> wechatList) {
        // 将 wechatList 转换为 Map，以便快速查找
        Map<Long, EvectionBean> wechatUserMap = wechatList.stream()
                .collect(Collectors.toMap(EvectionBean::getId, user -> user, (existing, replacement) -> existing));
        // 遍历 list，检查每个用户是否存在于 wechatList 中
        for (EvectionBean bean : list) {
            Long id = bean.getId();
            if (!wechatUserMap.containsKey(id)) {
                // 如果 userId 不存在于 wechatList，则插入到数据库 a
                    bean.setUuid(UUID.randomUUID().toString());
                    String jsonStr2 = FastJsonHelper.beanToJsonStr(bean);
                    String method2 = "insertWechatLeave";
                    String string2 = httpPost(method2, jsonStr2);
                    log.info("插入请假数据到小程序："+string2);
            } else {
                // 如果存在，则判断时间是否后于小程序时间
                EvectionBean wechatUser = wechatUserMap.get(id);
                if (bean.getUpdateTime().after(wechatUser.getUpdateTime())) {
                    // 如果 list 中的 updateTime 更新，则更新数据库 a
                    String jsonStr = FastJsonHelper.beanToJsonStr(bean);
                    String method = "updateWechatLeaveMsg";
                    String string = httpPost(method, jsonStr);
                    log.info("插入请假数据到小程序：" + string);
                }
            }
        }
    }


    @Resource
    private AttTasks attTasks;

    /**
     * 考勤数据同步定时器
     */
    @Scheduled(initialDelay = 6000 * 3,fixedDelay = 60000 * 30)
    @Async
    public void wechatAttTask() {
        log.info("--------考勤数据定时器开启------");
        index=4;
//        //小程序库人员考勤
        String jsonStr = "{}";
        String method = "getWechatAttList";
        String string = httpPost(method, jsonStr);
        List<AttSourceDataBean> attSourceList = FastJsonHelper.jsonArrStrToBeanList(string, AttSourceDataBean.class);
        attSourceList.forEach(bean -> {
            //判断是否外勤
            //1.0获取考勤规则的组织的
            String userName = bean.getName();
            // 如果Map中没有该userId的组织机构信息，则从数据库查询
            SysOrg orgInfo = dao.getOrgInfoByUserName(userName);
            if (orgInfo != null) {
                bean.setIdNumber(orgInfo.getIdNumber());
                double distanceMeters = 0;
                try {
                    distanceMeters = calculateDistance(bean.getAttLat(), bean.getAttLon(), orgInfo.getLat().doubleValue(), orgInfo.getLon().doubleValue(), DistanceCalculator.Unit.METERS);
                }catch (Exception e) {
                    e.printStackTrace();
                    distanceMeters = 1000000;
                }
               if (distanceMeters > orgInfo.getAttRange()) {
                    //外勤
                    bean.setIsOutsideAtt("1");
                } else {
                    //正常
                    bean.setIsOutsideAtt("2");
                }
            } else {
                //外勤
                bean.setIsOutsideAtt("1");
            }
        });
        //新增数据
        attSourceList.forEach(c -> {
            if ("0".equals(c.getAttType())) {
                int i = attTasks.checkTime(c.getAttCurrentTime());
                c.setAttType(String.valueOf(i));
            }
            //将00:00:00 至 04:59:59 时间变成att_current_day上一天的
            attTasks.changeAttCurrentDay(c);
        });
        //新增考勤到考勤来源表(数据过多时分批次插入)
        attTasks.insertAttSourceData(attSourceList);
        //将是否外勤更新到小程序库
//        dao.updateWechatAttList(attSourceList);
        String jsonStr2 = FastJsonHelper.beanListToJsonArrStr(attSourceList);
        String method2 = "updateWechatAttList";
        String string2 = httpPost(method2, jsonStr2);
        //将数据同步到黔送云库
        //1.先从黔送云库获取到在场人员的组织工程
        attSourceList.forEach(c -> {
            if(c.getIdNumber() != null){
                MapBean mapBean= dao.getProOrgToQsy(c);
                if(mapBean != null){
                    c.setProId(mapBean.getProId());
                    c.setOrgId(String.valueOf(mapBean.getOrgId()));
                }
            }
        });
        //2.推送到人员考勤表
        if(!attSourceList.isEmpty()){
            dao.pushAttDataToQsy(attSourceList);
        }
        log.info("--------考勤数据定时器完毕------");
    }

    private void syncFaceToDatabase(List<AttFaceBean> faceList, List<AttFaceBean> wechatFaceList) {
        Map<Long, AttFaceBean> wechatUserMap = faceList.stream()
                .collect(Collectors.toMap(AttFaceBean::getUserId, user -> user, (existing, replacement) -> existing));
        for (AttFaceBean user : wechatFaceList) {
            Long userId = user.getUserId();
            if (!wechatUserMap.containsKey(userId)) {
                //第一次录入人脸
                dao.insertWebFace(user);
            } else {
                //将未审核通过的数据更新到考勤库审核
                dao.updateWebFace(user);
            }
        }
    }

    private void syncListsToDatabase(List<SysUser> list, List<SysUser> wechatList) {
        // 将 wechatList 转换为 Map，以便快速查找
        Map<Long, SysUser> wechatUserMap = Optional.ofNullable(wechatList)
                .orElse(Collections.emptyList()).stream()
                .collect(Collectors.toMap(SysUser::getUserId, user -> user, (existing, replacement) -> existing));

        // 遍历 list，检查每个用户是否存在于 wechatList 中
        for (SysUser user : list) {
            Long userId = user.getUserId();
            if (!wechatUserMap.containsKey(userId)) {
                // 如果 userId 不存在于 wechatList，则插入到数据库 a
//                dao.insertWechatPerson(user);
                String jsonStr = FastJsonHelper.beanToJsonStr(user);
                String method = "insertWechatPerson";
                String string = httpPost(method, jsonStr);
            } else {
                // 如果存在，则判断时间是否后于小程序时间
                // 如果 userId 存在于 wechatList，则比较 updateTime
                SysUser wechatUser = wechatUserMap.get(userId);
                if (user.getUpdateTime().after(wechatUser.getUpdateTime())) {
                    // 如果 list 中的 updateTime 更新，则更新数据库 a
//                    dao.updateWechatPerson(user);
                    String jsonStr = FastJsonHelper.beanToJsonStr(user);
                    String method = "updateWechatPerson";
                    String string = httpPost(method, jsonStr);

                } else if (wechatUser.getUpdateTime().after(user.getUpdateTime())) {
                    //更新后端密码
                    dao.updateWebPassword(wechatUser);
                }
                //openId 单向更新
                if (StringUtils.isNotEmpty(wechatUser.getOpenId()) && !wechatUser.getOpenId().equals(user.getOpenId())) {
                    //更新后端openId
                    dao.updateWebOpenId(wechatUser);
                }
                //单项更新 isPd
                if (StringUtils.isNotEmpty(user.getIsPd()) && !user.getIsPd().equals(wechatUser.getIsPd())) {
                    //更新小程序isPd
//                    dao.updateWechatIsPd(user);
                    String jsonStr = FastJsonHelper.beanToJsonStr(user);
                    String method = "updateWechatIsPd";
                    String string = httpPost(method, jsonStr);
                }
            }
        }

        // 创建一个包含list中所有用户ID的集合
        Set<Long> userIdsInList = list.stream()
                .map(SysUser::getUserId)
                .collect(Collectors.toSet());
        // 遍历 wechatUserMap，检查每个用户是否存在于 list 中
        for (Long wechatUserId : wechatUserMap.keySet()) {
            if (!userIdsInList.contains(wechatUserId)) {
                // 如果 userId 不存在于 list，则从数据库 a 删除
                SysUser wechatUser = wechatUserMap.get(wechatUserId);
                // 执行删除操作
//            dao.deleteWechatPerson(wechatUser);
                String jsonStr = FastJsonHelper.beanToJsonStr(wechatUser);
                String method = "deleteWechatPerson";
                String string = httpPost(method, jsonStr);
            }
        }
    }

    private String httpPost(String method, String jsonStr) {
        try {
//            HttpResponse response = HttpRequest.post(IpAndPathConfig.getWechatUrl() + "/wechatData/" + method)
//                    .header("Content-Type", "application/json")
//                    .body(jsonStr)
//                    .execute();
            if(index > 0){
                HttpResponse response = HttpRequest.post(IpAndPathConfig.getWechatUrl() + "/wechatData/" + method)
                        .header("Content-Type", "application/json")
                        .header("token",token) // 添加Token到请求头
                        .body(jsonStr)
                        .execute();
                int statusCode = response.getStatus();
                System.out.println(response.body());
                JSONObject jsonObject = FastJsonHelper.jsonStrToJsonObj(response.body());
                if("401".equals(jsonObject.getString("code"))){
                    wechatLogin();
                    index--;
                    return httpPost(method, jsonStr);
                }
                if("200".equals(jsonObject.getString("code") ) ){
                    index = 4;
                }
                return jsonObject.getString("obj");
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 处理异常，例如记录日志或抛出自定义异常
            return "";
        }
        return "";
    }

    /**
     * 授予人脸重新录入权限时调用
     * @param user
     */
    public int updateWechatIsFace(SysUser user){
//        dao.updateWechatIsFace(user);
        String jsonStr = FastJsonHelper.beanToJsonStr(user);
        String method = "updateWechatIsFace";
        String string = httpPost(method, jsonStr);
        if("success".equals(string)){
            return 1;
        }else{
            return 0;
        }
    }

    /**
     * 审核人脸时调用
     * @String isCheck
     */
    public int checkWechatIsFace(SysUser user){
        String jsonStr = FastJsonHelper.beanToJsonStr(user);
        String method = "checkWechatIsFace";
        String string = httpPost(method, jsonStr);
        if("success".equals(string)){
            return 1;
        }else{
            return 0;
        }
    }

    public void wechatLogin() {
        OkHttpClient client = new OkHttpClient().newBuilder()
                .build();
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = null;
        try {
//            body = RequestBody.create(mediaType, "username=15240004260&password=GZkq@123456!");
            body = RequestBody.create(mediaType, "username="+ AESCBCUtil.encrypt("15240004260wechat")+"&password="+AESCBCUtil.encrypt("GZkq@123456!"));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        Request request = new Request.Builder()
                .url(IpAndPathConfig.getWechatUrl() + "/login")
                .method("POST", body)
                .addHeader("Connection", "keep-alive")
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            // 读取响应体为字符串
            String responseBody = response.body().string();
            // 使用FastJSON2解析JSON并映射到JSONObject
            JSONObject jsonObject = JSON.parseObject(responseBody);
            // 提取token字段
            this.token = jsonObject.getString("token");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}