package com.tzld.piaoquan.offline.job;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tzld.piaoquan.growth.common.common.enums.TimeEnum;
import com.tzld.piaoquan.growth.common.component.HttpPoolClient;
import com.tzld.piaoquan.growth.common.component.ProxyHttpPoolClient;
import com.tzld.piaoquan.growth.common.dao.mapper.*;
import com.tzld.piaoquan.growth.common.model.bo.XxlJobParam;
import com.tzld.piaoquan.growth.common.model.po.*;
import com.tzld.piaoquan.growth.common.service.WeComAccessTokenService;
import com.tzld.piaoquan.growth.common.utils.DateUtil;
import com.tzld.piaoquan.growth.common.utils.LarkRobotUtil;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.tzld.piaoquan.growth.common.common.constant.WeComConstant.*;

@Slf4j
@Component
public class WeComStaffDataJob {

    @Autowired
    private HttpPoolClient httpPoolClient;

    @Autowired
    private ProxyHttpPoolClient proxyHttpPoolClient;

    @Autowired
    private WeComAccessTokenService weComAccessTokenService;

    @Autowired
    private StaffMapper staffMapper;

    @Autowired
    private CorpMapper corpMapper;

    @Autowired
    private StaffStatisticsTotalMapper staffStatisticsTotalMapper;

    @Autowired
    private StaffGroupStatisticsTotalMapper staffGroupStatisticsTotalMapper;

    @Autowired
    private CorpStatisticsTotalMapper corpStatisticsTotalMapper;

    @XxlJob("syncStaffJob")
    public ReturnT<String> syncStaff(String param) {
        try {
            XxlJobParam xxlJobParam = new XxlJobParam();
            if (StringUtils.isNotEmpty(param)) {
                xxlJobParam = JSONObject.parseObject(param, XxlJobParam.class);
            }
            CorpExample corpExample = new CorpExample();
            if (xxlJobParam.getCorpId() != null) {
                corpExample.createCriteria().andIdEqualTo(xxlJobParam.getCorpId());
            }
            List<Corp> corps = corpMapper.selectByExample(corpExample);
            if (CollectionUtils.isEmpty(corps)) {
                return ReturnT.SUCCESS;
            }
            for (Corp corp : corps) {
                List<String> carrierIdList = getCarrierIdList(corp.getId());
                if (CollectionUtils.isEmpty(carrierIdList)) {
                    continue;
                }
                for (String carrierId : carrierIdList) {
                    JSONObject carrierInfo = getCarrierInfo(corp.getId(), carrierId);
                    StaffExample example = new StaffExample();
                    example.createCriteria().andCarrierIdEqualTo(carrierId).andCorpIdEqualTo(corp.getId());
                    List<Staff> staffList = staffMapper.selectByExample(example);
                    if (CollectionUtils.isEmpty(staffList)) {
                        Staff staff = new Staff();
                        staff.setCorpId(corp.getId());
                        staff.setCarrierId(carrierId);
                        if (Objects.nonNull(carrierInfo) && carrierInfo.containsKey("name")) {
                            staff.setRemark(carrierInfo.getString("name"));
                        } else {
                            staff.setRemark("");
                        }
                        staffMapper.insert(staff);
                    } else {
                        Staff staff = staffList.get(0);
                        if (Objects.nonNull(carrierInfo) && carrierInfo.containsKey("name")) {
                            staff.setRemark(carrierInfo.getString("name"));
                            staffMapper.updateByPrimaryKeySelective(staff);
                        }
                    }
                }
            }
        } catch (Exception e) {
            LarkRobotUtil.sendMessage("更新员工失败");
            log.error("insertStaff error", e);
        }
        return ReturnT.SUCCESS;
    }

    private List<String> getCarrierIdList(Long corpId) throws IOException {
        String weComAccessToken = weComAccessTokenService.getWeComAccessToken(corpId);
        String url = String.format(GET_WE_COM_FOLLOW_USER_LIST + "?access_token=%s", weComAccessToken);
        String res;
        if (corpId == 1L) {
            res = httpPoolClient.get(url);
        } else {
            res = proxyHttpPoolClient.get(url);
        }
        log.info("getCarrierIdList corp = {}, res={}", corpId, res);
        JSONObject jsonObject = JSONObject.parseObject(res);
        Integer errcode = jsonObject.getInteger("errcode");
        if (errcode == 0) {
            return jsonObject.getJSONArray("follow_user").stream().map(String::valueOf).collect(Collectors.toList());
        }
        return null;
    }

    private JSONObject getCarrierInfo(Long corpId, String userId) throws IOException {
        String weComAccessToken = weComAccessTokenService.getWeComAccessToken(corpId);
        String url = String.format(GET_WE_COM_FOLLOW_USER_DETAIL + "?access_token=%s", weComAccessToken);
        url = String.format(url + "&userid=%s", userId);
        String res;
        if (corpId == 1L) {
            res = httpPoolClient.get(url);
        } else {
            res = proxyHttpPoolClient.get(url);
        }
        log.info("getCarrierInfo corp = {} , userId = {}, res={}", corpId, userId, res);
        JSONObject jsonObject = JSONObject.parseObject(res);
        Integer errcode = jsonObject.getInteger("errcode");
        if (errcode == 0) {
            return jsonObject;
        }
        return null;
    }

    @XxlJob("statisticsTotalJob")
    public ReturnT<String> statisticsTotal(String param) throws IOException {
        String date;
        if (StringUtils.isNotEmpty(param)) {
            date = param;
        } else {
            date = DateUtil.getBeforeDayDateString1();
        }
        long startTime = DateUtil.dateStrToTimestamp(date, "yyyy-MM-dd");
        long endTime = startTime + TimeEnum.DAY.getTime() - 1;
        StaffExample staffExample = new StaffExample();
        staffExample.createCriteria().andIsDeleteEqualTo(0);
        List<Staff> staffs = staffMapper.selectByExample(staffExample);
        for (Staff staff : staffs) {
            statisticsStaffTotal(staff, startTime, endTime, date);
            statisticsStaffGroupTotal(staff, startTime, date);
        }
        StaffStatisticsTotalExample staffStatisticsTotalExample = new StaffStatisticsTotalExample();
        staffStatisticsTotalExample.createCriteria().andDateEqualTo(date);
        List<StaffStatisticsTotal> staffStatisticsTotals = staffStatisticsTotalMapper.selectByExample(staffStatisticsTotalExample);
        if (!CollectionUtils.isEmpty(staffStatisticsTotals)) {
            // 2. 分组并多字段求和（不使用构造方法）
            List<CorpStatisticsTotal> results = processStaffStatistics(staffStatisticsTotals);
            for (CorpStatisticsTotal corpStatisticsTotal : results) {
                corpStatisticsTotal.setDate(date);
                try {
                    corpStatisticsTotalMapper.insertSelective(corpStatisticsTotal);
                } catch (Exception e) {
                    log.error("insert corpStatisticsTotal error", e);
                }
            }
        }


        return ReturnT.SUCCESS;
    }

    public List<CorpStatisticsTotal> processStaffStatistics(List<StaffStatisticsTotal> staffStatisticsTotals) {
        // 使用 toMap 收集器高效分组和聚合
        Map<Long, CorpStatisticsTotal> resultMap = staffStatisticsTotals.stream()
                .collect(Collectors.toMap(
                        StaffStatisticsTotal::getCorpId,
                        this::convertToCorpStats,  // 方法引用转换
                        this::mergeCorpStats       // 方法引用合并
                ));

        return new ArrayList<>(resultMap.values());
    }

    private CorpStatisticsTotal mergeCorpStats(CorpStatisticsTotal existing, CorpStatisticsTotal newcomer) {
        existing.setChatCnt(existing.getChatCnt() + newcomer.getChatCnt());
        existing.setMessageCnt(existing.getMessageCnt() + newcomer.getMessageCnt());
        existing.setNegativeFeedbackCnt(existing.getNegativeFeedbackCnt() + newcomer.getNegativeFeedbackCnt());
        existing.setNewApplyCnt(existing.getNewApplyCnt() + newcomer.getNewApplyCnt());
        existing.setNewContactCnt(existing.getNewContactCnt() + newcomer.getNewContactCnt());
        return existing;
    }

    // 转换方法：将 Staff 对象转换为 Corp 对象
    private CorpStatisticsTotal convertToCorpStats(StaffStatisticsTotal staff) {
        CorpStatisticsTotal corp = new CorpStatisticsTotal();
        corp.setCorpId(staff.getCorpId());
        corp.setChatCnt(staff.getChatCnt());
        corp.setMessageCnt(staff.getMessageCnt());
        corp.setNegativeFeedbackCnt(staff.getNegativeFeedbackCnt());
        corp.setNewApplyCnt(staff.getNewApplyCnt());
        corp.setNewContactCnt(staff.getNewContactCnt());
        return corp;
    }

    private void statisticsStaffTotal(Staff staff, long startTime, long endTime, String date) throws IOException {
        Long corpId = staff.getCorpId();
        StaffStatisticsTotalExample example = new StaffStatisticsTotalExample();
        example.createCriteria().andCorpIdEqualTo(corpId).andStaffIdEqualTo(staff.getId()).andDateEqualTo(date);
        long l = staffStatisticsTotalMapper.countByExample(example);
        if (l > 0) {
            return;
        }
        String accessToken = weComAccessTokenService.getWeComAccessToken(corpId);
        String url = POST_WE_COM_USER_BEHAVIOR_DATA
                + "?access_token=" + accessToken;
        JSONObject params = new JSONObject();
        params.put("start_time", startTime);
        params.put("end_time", endTime);
        JSONArray userIds = new JSONArray();
        userIds.add(staff.getCarrierId());
        params.put("userid", userIds);
        String res;
        if (staff.getCorpId() == 1L) {
            res = httpPoolClient.post(url, params.toJSONString());
        } else {
            res = proxyHttpPoolClient.post(url, params.toJSONString());
        }
        if (StringUtils.isNotEmpty(res)) {
            JSONObject jsonObject = JSONObject.parseObject(res);
            Integer errcode = jsonObject.getInteger("errcode");
            if (errcode == 0) {
                JSONArray jsonArray = jsonObject.getJSONArray("behavior_data");
                if (!jsonArray.isEmpty()) {
                    JSONObject data = jsonArray.getJSONObject(0);
                    StaffStatisticsTotal statisticsTotal = new StaffStatisticsTotal();
                    statisticsTotal.setStatTime(data.getLong("stat_time"));
                    statisticsTotal.setChatCnt(data.getInteger("chat_cnt"));
                    statisticsTotal.setMessageCnt(data.getInteger("message_cnt"));
                    statisticsTotal.setNegativeFeedbackCnt(data.getInteger("negative_feedback_cnt"));
                    statisticsTotal.setNewApplyCnt(data.getInteger("new_apply_cnt"));
                    statisticsTotal.setNewContactCnt(data.getInteger("new_contact_cnt"));
                    statisticsTotal.setDate(date);
                    statisticsTotal.setCorpId(corpId);
                    statisticsTotal.setStaffId(staff.getId());
                    statisticsTotal.setUserId(staff.getCarrierId());
                    staffStatisticsTotalMapper.insertSelective(statisticsTotal);
                }
            }
        }
    }


    private void statisticsStaffGroupTotal(Staff staff, long startTime, String date) throws IOException {
        Long corpId = staff.getCorpId();
        StaffGroupStatisticsTotalExample example = new StaffGroupStatisticsTotalExample();
        example.createCriteria().andCorpIdEqualTo(corpId).andStaffIdEqualTo(staff.getId()).andDateEqualTo(date);
        long l = staffGroupStatisticsTotalMapper.countByExample(example);
        if (l > 0) {
            return;
        }
        String accessToken = weComAccessTokenService.getWeComAccessToken(corpId);
        String url = POST_WE_COM_USER_GROUP_CHAT_STATISTIC
                + "?access_token=" + accessToken;
        JSONObject params = new JSONObject();
        params.put("day_begin_time", startTime);
        JSONObject ownerFilter = new JSONObject();
        JSONArray userIds = new JSONArray();
        userIds.add(staff.getCarrierId());
        ownerFilter.put("userid_list", userIds);
        params.put("owner_filter", ownerFilter);
        System.out.println(JSONObject.toJSONString(params));
        String res;
        if (staff.getCorpId() == 1L) {
            res = httpPoolClient.post(url, params.toJSONString());
        } else {
            res = proxyHttpPoolClient.post(url, params.toJSONString());
        }
        if (StringUtils.isNotEmpty(res)) {
            JSONObject jsonObject = JSONObject.parseObject(res);
            Integer errcode = jsonObject.getInteger("errcode");
            if (errcode == 0) {
                JSONArray jsonArray = jsonObject.getJSONArray("items");
                if (!jsonArray.isEmpty()) {
                    StaffGroupStatisticsTotal statisticsTotal = new StaffGroupStatisticsTotal();
                    JSONObject data = jsonArray.getJSONObject(0).getJSONObject("data");
                    statisticsTotal.setStatTime(jsonArray.getJSONObject(0).getLong("stat_time"));
                    statisticsTotal.setNewChatCnt(data.getInteger("new_chat_cnt"));
                    statisticsTotal.setChatTotal(data.getInteger("chat_total"));
                    statisticsTotal.setChatHasMsg(data.getInteger("chat_has_msg"));
                    statisticsTotal.setNewMemberCnt(data.getInteger("new_member_cnt"));
                    statisticsTotal.setMemberTotal(data.getInteger("member_total"));
                    statisticsTotal.setMemberHasMsg(data.getInteger("member_has_msg"));
                    statisticsTotal.setMsgTotal(data.getInteger("msg_total"));
                    statisticsTotal.setMigrateTraineeChatCnt(data.getInteger("migrate_trainee_chat_cnt"));
                    statisticsTotal.setDate(date);
                    statisticsTotal.setCorpId(corpId);
                    statisticsTotal.setStaffId(staff.getId());
                    statisticsTotal.setUserId(staff.getCarrierId());
                    staffGroupStatisticsTotalMapper.insertSelective(statisticsTotal);
                }
            }
        }
    }

}
