package cn.com.ctop.common.module.achievements.service.impl;

import cn.com.ctop.common.module.achievements.mapper.DesignerMapper;
import cn.com.ctop.common.module.achievements.service.IDesignerService;
import cn.com.ctop.common.module.utils.Check;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.ctop.service.IMaterialReportOverViewService;
import org.jeecg.modules.system.service.ISysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.ToDoubleFunction;

/**
 * 设计人员绩效
 *
 * @author: zian Y
 * @date: 2022-09-28
 * @cersion: V1.0
 */

@Slf4j
@Service
public class DesignerServiceImpl implements IDesignerService {
    @Resource
    private DesignerMapper designerMapper;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private IMaterialReportOverViewService materialReportOverViewService;
    private ToDoubleFunction<JSONObject> getJSONObject;

    /**
     * 判断 人员 季度消耗 是否达标
     * 一季度3个月 平均每个月80w消耗
     * 此季度素材总消耗大于240w，则为达标，否则为不达标；
     * 此外需要考虑人员的入离职日期，如果5月入职，则只计算5、6月是否达标即可，则为每个月80w的消耗目标；
     * frozenTime 离职时间
     * createTime 员工入职时间
     *
     * @return
     */
    public Double getMaterialCost(String frozenTime, String createTime, int yearTime, int monthTime) {

//String frozenTime = "";
        //String createTime = "2022-11-02 12:23:23";

        //绩效 = 在职月份 * 80w 额度
        Double cost = new Double("800000");
        int i = 3;

        /**
         * 人员离职
         */
        if (frozenTime != null) {
            String yearF = DateUtils.getYear("yyyy-MM-dd", frozenTime);
            if (!yearF.equals(String.valueOf(yearTime))) {
                log.info("离职-----离职时间是：{},查询季度{} 绩效按照0计算。", frozenTime, monthTime);
                return 0 * cost;
            }


            Date date = DateUtils.str2Date(frozenTime, new SimpleDateFormat("yyyy-MM-dd"));
            // 判断时间所在的季度
            int quarterTime = DateUtils.getQuarter(date);

            //季度查询时间 超过 离职时间 则比例为0 绩效 无
            if (quarterTime < monthTime) {
                i = 0;
                log.info("离职-----离职时间是：{},查询季度{} 绩效按照0计算。当前时间是：{},", frozenTime, monthTime, new Date());

            }

            if (quarterTime > monthTime) {
                log.info("离职-----离职时间是：{}，查询季度{}，绩效按照240计算。当前时间是：{},", frozenTime, monthTime, new Date());

            }

            //离职时间 是否是当前季度
            if (quarterTime == monthTime) {
                Map<String, Object> map = DateUtils.getCurrentQuarterMonths(monthTime);
                //离职时间所在 月份
                String month = DateUtils.getMonth("yyyy-MM-dd", frozenTime);
                //离职时间所在的季度 的全部 月份
                String[] quarter = (String[]) map.get("quarter");
                //判断当前离职所在的月份 与当前季度中的月份集合 并获取下标  下标+1 则是 在职月份i
                int j = Collections.indexOfSubList(Arrays.asList(quarter), Arrays.asList(month));
                i = j + 1;
                log.info("离职-----离职时间是：{}在查询季度{}范围内！系数为{}个月的绩效数据--->{}", frozenTime, monthTime, i, i * cost);

            }
            //return i * cost;

        } else {
            String yearC = DateUtils.getYear("yyyy-MM-dd", createTime);
            if (!yearC.equals(String.valueOf(yearTime))) {
                log.info("在职-----入职时间是：{},查询季度{} 绩效按照240计算。", createTime, monthTime);
                return i * cost;
            }
            Date date = DateUtils.str2Date(createTime, new SimpleDateFormat("yyyy-MM-dd"));
            // 判断时间所在的季度
            int quarterTime = DateUtils.getQuarter(date);
            //查询入职前的 比例
            //季度查询时间 超过 入职时间  绩效0
            if (quarterTime < monthTime) {
                log.info("在职-----入职时间是：{},查询季度{} 绩效按照240计算。当前时间是：{},", createTime, monthTime, new Date());
            }
            //查询入职后的 比例
            if (quarterTime > monthTime) {
                i = 0;
                log.info("在职-----入职时间是：{}，查询季度{}，绩效按照0计算。当前时间是：{},", createTime, monthTime, new Date());
            }

            //入职时间 在当前季度
            if (quarterTime == monthTime) {
                Map<String, Object> map = DateUtils.getCurrentQuarterMonths(monthTime);
                //月份
                //入职时间所在 月份
                String month = DateUtils.getMonth("yyyy-MM-dd", createTime);
                //季度
                String[] quarter = (String[]) map.get("quarter");
                //判断当前离职所在的月份 与当前季度中的月份集合 并获取下标  下标+1 则是 在职月份i
                int j = Collections.indexOfSubList(Arrays.asList(quarter), Arrays.asList(month));
                i = j + 1;
                log.info("在职-----入职时间是：{}在查询季度{}内！系数为{}个月的绩效数据--->{}", createTime, monthTime, i, i * cost);
                return i * cost;
            }
            ;
        }
        return i * cost;
    }


    /**
     * 离职发放比例
     * frozenTime 离职时间
     *
     * @return
     */
    public Double userHappyProbability(String frozenTime, int monthTime) {

        //离职发放比例
        Double userHappyProbability = new Double("1");
        if (!Check.isNull(frozenTime)) {
            //根据时间获取季度
            //离职时间所在的季度 是否和 查询季度相同 相同则判断 不同 则比例为1

            //当前季度的 月份
            Map<String, Object> map = DateUtils.getCurrentQuarterMonths(monthTime);
            //季度
            String[] quarter = (String[]) map.get("quarter");
            String month = DateUtils.getMonth("yyyy-MM-dd", frozenTime);
            if (Arrays.binarySearch(quarter, month) < 0) {
                return userHappyProbability;
            }


            //离职  获取 天
            String day = DateUtils.getDay("yyyy-MM-dd", frozenTime);

            //15日之前离职 不发
            if (Integer.valueOf(day) < 15) {
                userHappyProbability = new Double("0");
            }

            // 15号之后离职，发50%
            if (Integer.valueOf(day) >= 15) {
                userHappyProbability = new Double("0.5");
            }

            //离职时间所在季度的最后一天
            String endDay = DateUtils.getQuarterEndDay(frozenTime);
            //最后一天离职 发放比例为1
            // 离职时间 > = 最后一天
            if (DateUtils.str2Date(frozenTime, new SimpleDateFormat("yyyy-MM-dd")).getTime() >=
                    DateUtils.str2Date(endDay, new SimpleDateFormat("yyyy-MM-dd")).getTime()) {
                userHappyProbability = new Double("1");
            }


        }

        return userHappyProbability;
    }

    /**
     * @param userId
     * @description:爆款视频数据
     * @return: org.jeecg.common.api.vo.Result
     * @author: zianY
     */
    public void getHotVideoData(JSONObject jsonObject, String yearTime, List<Map<String, Integer>> timeMap) {
        String userId = jsonObject.getString("userId");
        String roleName = null;
        //查询用户角色
        String roleCode = roleService.getRoleCodeByUserId(userId);
        if (roleCode.contains("clip")) {
            roleName = "clip";
        } else if (roleCode.contains("shot")) {
            roleName = "shot";
        } else if (roleCode.contains("plan")) {
            roleName = "plan";
        } else {
            roleName = "all";
        }
        Map<String, Integer> month1 = timeMap.get(0);
        Map<String, Integer> month2 = timeMap.get(1);
        Map<String, Integer> month3 = timeMap.get(2);
        JSONObject bytedanceJson = designerMapper.getHotVideoData(userId, roleName, 1, month1, month2, month3);
        JSONObject kuaishouJson = designerMapper.getHotVideoData(userId, roleName, 2, month1, month2, month3);
        jsonObject.put("bytedance", bytedanceJson);
        jsonObject.put("kuaishou", kuaishouJson);
    }


    public void getDesignerAchievements(JSONObject jsonObject, String yearTime, List<Map<String, Integer>> timeMap) {
        String userId = jsonObject.getString("userId");
        Map<String, Object> resultMap = new HashMap<>();
        Map<String, Integer> month1 = timeMap.get(0);
        Map<String, Integer> month2 = timeMap.get(1);
        Map<String, Integer> month3 = timeMap.get(2);
        List<JSONObject> bytedanceJson = designerMapper.getQuarterDesignerAchievementsByTedance(userId, month1, month2, month3);
        List<JSONObject> kuaishouJson = designerMapper.getQuarterDesignerAchievementsByKuaishou(userId, month1, month2, month3);
        jsonObject.put("byteDanceData", bytedanceJson);
        jsonObject.put("kuaiShouData", kuaishouJson);

    }

    public JSONObject getDesignerCommission(String userId, String yearTime, String monthTime, List<Map<String, Integer>> timeMap) {
        String roleCode = roleService.getRoleCodeByUserId(userId);

        //人员离职信息
        JSONObject userFrozen = designerMapper.getUserFrozenInfo(userId);

        //离职时间
        String frozenTime = userFrozen.getString("frozenTime");
        //入职时间
        String createTime = userFrozen.getString("createTime");


        List<Map<String, Object>> quarterCostList = new ArrayList<>();
        List<Map<String, Object>> leaderCostList = new ArrayList<>();
        List<JSONObject> listBytedanceCost = new ArrayList<>();
        List<JSONObject> listKuaishouCost = new ArrayList<>();
        for (Map<String, Integer> month : timeMap) {
            //季度 分媒体 素材消耗 分月查询
            List<JSONObject> bytedanceQuarterCost = designerMapper.getDesignerBytedanceQuaterCost(userId, month.get("startTime"), month.get("endTime"));
            List<JSONObject> kuaishouQuarterCost = designerMapper.getDesignerKuaishouQuaterCost(userId, month.get("startTime"), month.get("endTime"));
            listBytedanceCost.addAll(bytedanceQuarterCost);
            listKuaishouCost.addAll(kuaishouQuarterCost);


            //管理消耗 分月查询
            List<JSONObject> leaderCost = designerMapper.getDesignerManagerLeaderCost(userId, month.get("startTime"), month.get("endTime"));

            //离职 提成系数
            //Double a = userHappyProbability(frozenTime,Integer.valueOf(monthTime));
            Double userHappyProbability = new Double(1);
            if (!Check.isNull(frozenTime)) {
                //离职时间
                int frozenT = DateUtils.getDateInteger(frozenTime);

                //设计组长 看月份  如果6月离职的，则只计算4、5月份的，与日期无关
                if (roleCode.equalsIgnoreCase("designTeamLeader")) {
                    if (frozenT > month.get("endTime")) {
                        userHappyProbability = new Double(1);
                    } else {
                        userHappyProbability = new Double(0);
                    }
                }
            }

            Map<String, Object> leaderCostMap = new HashMap<>();
            leaderCostMap.put("xishu", userHappyProbability);
            leaderCostMap.put("bytedanceCost", new Double(leaderCost.get(0).getString("cost")) * userHappyProbability);
            leaderCostMap.put("kuaishouCost", new Double(leaderCost.get(1).getString("cost")) * userHappyProbability);
            leaderCostList.add(leaderCostMap);

        }
        Double bytedanceCost = listBytedanceCost.stream().mapToDouble(json -> json.getDouble("cost")).reduce(Double::sum).orElse(new Double("0"));
        Double kuaishouCost = listKuaishouCost.stream().mapToDouble(json -> json.getDouble("cost")).reduce(Double::sum).orElse(new Double("0"));
        Map<String, Object> bytedanceMap = new HashMap<>();
        Map<String, Object> kuaishouMap = new HashMap<>();
        bytedanceMap.put("type", "byteDance");
        bytedanceMap.put("cost", String.format("%.3f", bytedanceCost));
        kuaishouMap.put("type", "kuaiShou");
        kuaishouMap.put("cost", String.format("%.3f", kuaishouCost));
        quarterCostList.add(bytedanceMap);
        quarterCostList.add(kuaishouMap);

        //季度 分媒体 素材消耗
        userFrozen.put("quarterCostList", quarterCostList);

        //季度素材 总消耗
        Double tatolCost = quarterCostList.stream().mapToDouble(json -> new Double(json.get("cost") + "")).reduce(Double::sum).orElse(new Double("0"));
        userFrozen.put("tatolQuarterCost", String.format("%.3f", tatolCost));

        //季度 管理消耗汇总
        Double bytedanceLeaderCost = leaderCostList.stream().mapToDouble(json -> new Double(json.get("bytedanceCost") + "")).reduce(Double::sum).orElse(new Double("0"));
        Double kuaishouLeaderCost = leaderCostList.stream().mapToDouble(json -> new Double(json.get("kuaishouCost") + "")).reduce(Double::sum).orElse(new Double("0"));
        userFrozen.put("leaderCost", String.format("%.3f", bytedanceLeaderCost + kuaishouLeaderCost));


        //判断素材消耗是否达标
        Double flag = getMaterialCost(frozenTime, createTime, Integer.valueOf(yearTime), Integer.valueOf(monthTime));
        String materialCostQualifiedFlag = tatolCost >= flag ? "是" : "否";
        userFrozen.put("materialCostQualifiedFlag", materialCostQualifiedFlag);

        //爆款素材数量 分月查询
        JSONObject hotVideoNum = designerMapper.getUserHotMaterialQuarter(userId, timeMap.get(0).get("startTime"), timeMap.get(2).get("endTime"));
        int hotVideoN = Check.isNull(hotVideoNum) ? 0 : hotVideoNum.getInteger("hotVideoNum");
        userFrozen.put("hotVideoNum", hotVideoN);


        //爆款总量 开屏爆款数量 + 爆款数量
        int hotVideoTotalNum = userFrozen.getInteger("openHotVideoNum") + hotVideoN;
        userFrozen.put("hotVideoTotalNum", hotVideoTotalNum);


        Map<String, Integer> month1 = timeMap.get(0);
        Map<String, Integer> month2 = timeMap.get(1);
        Map<String, Integer> month3 = timeMap.get(2);
        List<JSONObject> bytedanceJson = designerMapper.getQuarterDesignerAchievementsByTedance(userId, month1, month2, month3);
        List<JSONObject> kuaishouJson = designerMapper.getQuarterDesignerAchievementsByKuaishou(userId, month1, month2, month3);
        List<List<JSONObject>> bytedance = Lists.partition(bytedanceJson, 3);
        List<List<JSONObject>> kuaishou = Lists.partition(kuaishouJson, 3);
        //提成 分月份
        List<JSONObject> commissionList = new ArrayList<>();
        for (int i = 0; i < bytedance.size(); i++) {
            JSONObject commissionJson = new JSONObject();
            Double bytedanceCommission = bytedance.get(i).stream().mapToDouble(json -> json.getDouble("commission")).reduce(Double::sum).orElse(new Double("0"));
            Double kuaishouCommission = kuaishou.get(i).stream().mapToDouble(json -> json.getDouble("commission")).reduce(Double::sum).orElse(new Double("0"));
            Double userHappyProbability = new Double(1);
            if (!Check.isNull(frozenTime)) {
                //离职时间
                int frozenT = DateUtils.getDateInteger(frozenTime);
                int startTime = 0;
                int endTime = 0;
                if (i == 0) {
                    startTime = month1.get("startTime");
                    endTime = month1.get("endTime");
                } else if (i == 1) {
                    startTime = month2.get("startTime");
                    endTime = month2.get("endTime");
                } else {
                    startTime = month3.get("startTime");
                    endTime = month3.get("endTime");
                }
                // 日期转换 20221021 ===>>> 2022-10-21
                String day = DateUtils.getStrDateToInt(startTime);
                //获取月份的 中间的日期 20221015
                int middleDay = DateUtils.subMonthMiddleDay(day);

                //个人看日期
                // 如果当月15日之前离职，当月不发；
                // 15号之后离职，发50%；
                // 若月底最后一天离职，则发放100
                if (!roleCode.equalsIgnoreCase("designTeamLeader")) {
                    if (frozenT < middleDay) {
                        userHappyProbability = new Double(0);
                    }
                    if (frozenT > middleDay && frozenT < endTime) {
                        userHappyProbability = new Double(0.5);
                    }
                    if (frozenT == endTime) {
                        userHappyProbability = new Double(1);
                    }
                }
            }
            commissionJson.put("monthTime", bytedance.get(i).get(0).getBigInteger("monthTime"));
            commissionJson.put("xishu", userHappyProbability);
            commissionJson.put("commission", String.format("%.3f", (bytedanceCommission + kuaishouCommission) * userHappyProbability));
            commissionList.add(commissionJson);
        }
        bytedanceJson.get(0);
        userFrozen.put("commissionList", commissionList);


        //季度提成汇总
        BigDecimal totalCommissionBd = commissionList.stream().map(json -> json.getBigDecimal("commission")).reduce(BigDecimal.ZERO, BigDecimal::add);
        Double totalCommission = totalCommissionBd.doubleValue();

        //负责人提成 如果是负责人 （设计组长） 管理消耗 千三的20%
        Double designerLeaderCommission = new Double("0");

        if (roleCode.equalsIgnoreCase("designTeamLeader")) {
            Double designerLeaderCommissionBytedance = bytedanceLeaderCost * 0.002 * 0.2;
            Double designerLeaderCommissionKuaishou = kuaishouLeaderCost * 0.003 * 0.2;
            designerLeaderCommission = designerLeaderCommissionBytedance + designerLeaderCommissionKuaishou;
        }
        userFrozen.put("designerLeaderCommission", String.format("%.3f", designerLeaderCommission));

        //提成汇总 = 季度汇总 + 负责人提成
        totalCommission += designerLeaderCommission;
        userFrozen.put("totalCommission", totalCommission);

        //离职发放比例
        Double userHappyProbability = userHappyProbability(frozenTime, Integer.valueOf(monthTime));
        userFrozen.put("userHappyProbability", userHappyProbability);

        /**
         * 爆款达标 提成发放系数
         * 在季度中
         * 爆款 >= 10个 消耗>=240w 绩效 100%
         * 爆款 < 10 消耗 >= 240w 绩效50%
         * 爆款<=0 绩效 >= 240w 不发
         * 爆款>=10 绩效<=240w 不发
         * 其中的绩效240 根据入职或离职时间按月计算 使用字段materialCostQualifiedFlag
         *
         */
        Double coefficient = new Double("0");
        if (materialCostQualifiedFlag.equals("是")) {
            if (hotVideoTotalNum >= 10) {
                coefficient = new Double("1");
            }
            if (hotVideoTotalNum > 0 && hotVideoTotalNum < 10) {
                coefficient = new Double("0.5");
            }
        }
        userFrozen.put("coefficient", coefficient);

        //提成发放金额 = 总提成 * 爆款达标发放系数
        Double userHappyGetMoney = totalCommission * coefficient;
        userFrozen.put("userHappyGetMoney", String.format("%.3f", userHappyGetMoney));

        return userFrozen;
    }


    @Override
    public Result updateUserHappyProbability(JSONObject jsonObject) {
        designerMapper.updateUserHappyProbability(jsonObject.getString("userId"),
                jsonObject.getString("openScreenNum"),
                jsonObject.getString("paySalary"),
                jsonObject.getString("remarks"));
        return Result.successMsg("修改成功", null);


    }


    @Override
    public Result getDesignerBasicsAndHotVideoInfo(String userId, String yearTime, String monthTime, int pageNum, int pageSize) {
        //取当前时间的季度的月份
        List<Map<String, Integer>> timeMap = DateUtils.getQuarStartAndEndTime(Integer.valueOf(monthTime));
        //基础信息 + 爆款信息
        PageInfo<JSONObject> baseics = getDesignBasicsInfoList(userId, pageNum, pageSize, timeMap);
        for (JSONObject jsonObject : baseics.getList()) {
            getHotVideoData(jsonObject, yearTime, timeMap);
        }
        return Result.successMsg("基础+爆款查询成功。", baseics);


    }


    @Override
    public Result getDesignerBasicsAndAch(String userId, String yearTime, String monthTime, int pageNum, int pageSize) {
        long startTime = System.currentTimeMillis() / 1000;
        //取当前时间的季度的月份
        List<Map<String, Integer>> timeMap = DateUtils.getQuarStartAndEndTime(Integer.valueOf(monthTime));
        //基础信息 + 绩效
        PageInfo<JSONObject> baseics = getDesignBasicsInfoList(userId, pageNum, pageSize, timeMap);
        long endTime1 = System.currentTimeMillis() / 1000;
        System.out.println("------------------查询人员用时---------->" + (endTime1 - startTime) + "S");
        for (JSONObject jsonObject : baseics.getList()) {
            //绩效
            getDesignerAchievements(jsonObject, yearTime, timeMap);
        }
        long endTime = System.currentTimeMillis() / 1000;
        System.out.println("------------------总共用时---------->" + (endTime - startTime) + "S");
        return Result.successMsg("基础+绩效查询成功。", baseics);
    }


    @Override
    public Result getDesignerBasicsAndAchAndComInfo(String userId, String yearTime, String monthTime, int pageNum, int pageSize) {
        //取当前时间的季度的月份
        List<Map<String, Integer>> timeMap = DateUtils.getQuarStartAndEndTime(Integer.valueOf(monthTime));
        //基础信息 +提成
        PageInfo<JSONObject> baseics = getDesignBasicsInfoList(userId, pageNum, pageSize, timeMap);
        for (JSONObject jsonObject : baseics.getList()) {
            //提成
            JSONObject userFrozen = getDesignerCommission(jsonObject.getString("userId"), yearTime, monthTime, timeMap);
            jsonObject.put("userFrozen", userFrozen);
        }
        return Result.successMsg("基础+提成查询成功。", baseics);
    }

    /**
     * 获取人员信息
     */
    private PageInfo<JSONObject> getDesignBasicsInfoList(String userId, int pageNum, int pageSize, List<Map<String, Integer>> timeMap) {
        List<String> roleCodes = new ArrayList<>();
        Set<String> userIdList = new HashSet<>();
        //查询用户角色
        String roleCode = roleService.getRoleCodeByUserId(userId);
        if (roleCode.contains("admin")||"db2d59e9b4a3b18629c838fd7f5b58d8".equals(userId)) {
            //查询设计部门所有人
            roleCodes.add("设计");
            roleCodes.add("平面");
            roleCodes.add("制片");
            roleCodes.add("策划");
            roleCodes.add("拍摄");
            roleCodes.add("剪辑");

        } else if (roleCode.contains("Leader")) {
            //查询所有包含自己的下级
            userIdList = materialReportOverViewService.recursiveQuerySubordinate(userId);
        } else {
            userIdList.add(userId);
        }
        Integer startTime = timeMap.get(0).get("startTime");
        Integer endTime = timeMap.get(2).get("endTime");

        PageHelper.startPage(pageNum, pageSize);
        List<JSONObject> list = designerMapper.getDesignerUserInfo(roleCodes, userIdList, startTime, endTime);
        PageInfo<JSONObject> pageInfo = new PageInfo<>(list);
        return pageInfo;
    }


    @Override
    public Result getUserByRoleName(String roleName) {
        List<JSONObject> list = designerMapper.getUserByRoleName(roleName);
        return Result.successMsg("查询成功。", list);
    }


}
