package cn.com.ctop.report.service.impl;

import cn.com.ctop.common.constant.AccountReportConstants;
import cn.com.ctop.common.constant.CtopAdConstant;
import cn.com.ctop.common.entity.Project;
import cn.com.ctop.common.mapper.ProjectMapper;
import cn.com.ctop.common.mapper.SysDepartMapper;
import cn.com.ctop.common.mapper.SysRoleMapper;
import cn.com.ctop.common.service.ISysUserService;
import cn.com.ctop.common.utils.JsonResourceUtil;
import cn.com.ctop.common.utils.LinkUtils;
import cn.com.ctop.report.entity.AccountAttributionInfo;
import cn.com.ctop.report.mapper.AccountAttributionInfoMapper;
import cn.com.ctop.report.service.AccountAttributionInfoService;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.SystemDateConstant;
import org.jeecg.common.system.entity.SysDepart;
import org.jeecg.common.system.entity.SysUser;
import org.jeecg.common.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class AccountAttributionInfoServiceImpl extends ServiceImpl<AccountAttributionInfoMapper, AccountAttributionInfo> implements AccountAttributionInfoService {
    @Resource
    private AccountAttributionInfoMapper accountAttributionInfoMapper;
    @Autowired
    private ISysUserService sysUserService;
    @Resource
    private SysRoleMapper sysRoleMapper;
    @Resource
    private SysDepartMapper sysDepartMapper;
    @Resource
    private ProjectMapper projectMapper;
    @Override
    public void reloadData() {
        accountAttributionInfoMapper.reloadData();
    }

    @Override
    public List<AccountAttributionInfo> getAccountInfoList(String userId, String type){
        List<Integer> mediaList = new ArrayList<>();
        if (type.equals(CtopAdConstant.PLATFORM_TYPE_BYTEDANCE_PY)) {
            mediaList.add(CtopAdConstant.PLATFORM_TYPE_BYTEDANCE_INT);
            mediaList.add(CtopAdConstant.PLATFORM_TYPE_BYTEDANCE_INSIDE_INT);
        } else if (type.equals(CtopAdConstant.PLATFORM_TYPE_KUAISHOU_PY)) {
            mediaList.add(CtopAdConstant.PLATFORM_TYPE_KUAISHOU_INT);
            mediaList.add(CtopAdConstant.PLATFORM_TYPE_KUAISHOU_INSIDE_INT);
        }
        String roleCode = sysRoleMapper.getRoleCodeByUserId(userId);
        //管理员查所有
        if("admin".equals(roleCode)){
            return accountAttributionInfoMapper.selectByParams(mediaList,null,null,null);
        }
        //公司负责人
        SysDepart company = sysDepartMapper.getDepartByParams(userId,1);
        if(null != company){
            return accountAttributionInfoMapper.selectByParams(mediaList,company.getOrgCode()+"%",null,null);
        }
        //部门负责人
        SysDepart orgInfo = sysDepartMapper.getDepartByParams(userId,null);
        if(null!=orgInfo){
            return accountAttributionInfoMapper.selectByParams(mediaList,orgInfo.getOrgCode()+"%",null,null);
        }
        //项目负责人
        List<Project> projectList = projectMapper.getListByParams(mediaList,userId);
        if(null!=projectList&&!projectList.isEmpty()){
            List<Long> projectIds = new ArrayList<>();
            for (Project p:projectList) {
                projectIds.add(p.getId());
            }
            return accountAttributionInfoMapper.selectByParams(mediaList,null,projectIds,null);
        }
        //查询是否存在下级
        List<String> userIds = sysUserService.treeUserInfo(userId);
        return accountAttributionInfoMapper.selectByParams(mediaList,null,null,userIds);
    }

    @Override
    public JSONArray getProjectAccountByUserId(String userId, String mediaType) {
        List<AccountAttributionInfo>accountAttributionInfos = getAccountInfoList(userId,mediaType);
        Map<Long,Long> projectIdMaps = new HashMap<>();
        for(AccountAttributionInfo attributionInfo:accountAttributionInfos){
            if(null!=attributionInfo&&null!=attributionInfo.getProjectId()&&attributionInfo.getProjectId()!=0){
                projectIdMaps.putIfAbsent(attributionInfo.getProjectId(),attributionInfo.getProjectId());
            }
        }
        JSONArray projectInfos = new JSONArray();
        if(projectIdMaps.isEmpty()){
            return projectInfos;
        }
        for (Long key : projectIdMaps.keySet()) {
            List<AccountAttributionInfo>accountInfos = getAccountInfoListByProjectId(key,accountAttributionInfos);
            JSONObject projectInfo = new JSONObject();
            if(!accountInfos.isEmpty()){
                projectInfo.put("projectId",accountInfos.get(0).getProjectId());
                projectInfo.put("projectName",accountInfos.get(0).getProjectName());
                projectInfo.put("advertiserName",accountInfos.get(0).getAdvertiserName());
                projectInfo.put("advertiserId",accountInfos.get(0).getAdvertiserId());
                projectInfo.put("accountList",accountInfos);
                projectInfos.add(projectInfo);
            }
        }
        return projectInfos;
    }

    private List<AccountAttributionInfo> getAccountInfoListByProjectId(Long projectId, List<AccountAttributionInfo> accountAttributionInfos) {
        List<AccountAttributionInfo>result = new ArrayList<>();
        for(AccountAttributionInfo attributionInfo:accountAttributionInfos){
            if(null!=attributionInfo&&null!=attributionInfo.getProjectId()&&attributionInfo.getProjectId().equals(projectId)){
                result.add(attributionInfo);
            }
        }
        return result;
    }

    @Override
    public JSONArray getMaterialProjectAccountByUserId(String userId, String mediaType) {
        List<AccountAttributionInfo>accountAttributionInfos = getAccountInfoList(userId,mediaType);
        Map<Long,Long> projectIdMaps = new HashMap<>();
        for(AccountAttributionInfo attributionInfo:accountAttributionInfos){
            projectIdMaps.putIfAbsent(attributionInfo.getProjectId(),attributionInfo.getProjectId());
        }
        JSONArray projectInfos = new JSONArray();
        if(projectIdMaps.isEmpty()){
            return projectInfos;
        }
        for (Long key : projectIdMaps.keySet()) {
            List<AccountAttributionInfo>accountInfos = accountAttributionInfos.stream().filter(a->a.getProjectId().equals(key)).collect(Collectors.toList());
            JSONObject projectInfo = new JSONObject();
            projectInfo.put("projectId",accountInfos.get(0).getProjectId());
            projectInfo.put("projectName",accountInfos.get(0).getProjectName());
            projectInfo.put("advertiserName",accountInfos.get(0).getAdvertiserName());
            projectInfo.put("advertiserId",accountInfos.get(0).getAdvertiserId());
            projectInfo.put("accountInfos",accountInfos);
            projectInfos.add(projectInfo);
        }
        return projectInfos;
    }

    @Override
    public List<AccountAttributionInfo> getMaterialAccountInfoList(String userId, String mediaType) {
        List<Integer> mediaList = new ArrayList<>();
        if (mediaType.equals(CtopAdConstant.PLATFORM_TYPE_BYTEDANCE)) {
            mediaList.add(CtopAdConstant.PLATFORM_TYPE_BYTEDANCE_INT);
            mediaList.add(CtopAdConstant.PLATFORM_TYPE_BYTEDANCE_INSIDE_INT);
        } else if (mediaType.equals(CtopAdConstant.PLATFORM_TYPE_KUAISHOU)) {
            mediaList.add(CtopAdConstant.PLATFORM_TYPE_KUAISHOU_INT);
            mediaList.add(CtopAdConstant.PLATFORM_TYPE_KUAISHOU_INSIDE_INT);
        }
        String roleCode = sysRoleMapper.getRoleCodeByUserId(userId);
        //管理员查所有
        if("admin".equals(roleCode)){
            return accountAttributionInfoMapper.selectByParams(mediaList,null,null,null);
        }
        //公司负责人
        SysDepart company = sysDepartMapper.getDepartByParams(userId,1);
        if(null != company){
            return accountAttributionInfoMapper.selectByParams(mediaList,company.getOrgCode()+"%",null,null);
        }
        //部门负责人
        SysDepart orgInfo = sysDepartMapper.getDepartByParams(userId,null);
        if(null!=orgInfo){
            return accountAttributionInfoMapper.selectByParams(mediaList,orgInfo.getOrgCode()+"%",null,null);
        }
        //项目负责人
        List<Project> projectList = projectMapper.getListByParams(mediaList,userId);
        if(null!=projectList&&!projectList.isEmpty()){
            List<Long> projectIds = new ArrayList<>();
            for (Project p:projectList) {
                projectIds.add(p.getId());
            }
            return accountAttributionInfoMapper.selectByParams(mediaList,null,projectIds,null);
        }
        //设计组长,剪辑，编导，拍摄
        if("designTeamLeader".equals(roleCode)||"plan".equals(roleCode)||"clip".equals(roleCode)||"shot".equals(roleCode)){
            return this.selectDesignAccountByParams(mediaList,userId);
        }

        //查询是否存在下级
        List<String> userIds = sysUserService.treeUserInfo(userId);
        return accountAttributionInfoMapper.selectByParams(mediaList,null,null,userIds);
    }

    private List<AccountAttributionInfo> selectDesignAccountByParams(List<Integer> mediaList, String designUserId) {
        return accountAttributionInfoMapper.selectDesignAccuntsByParams(mediaList,designUserId);
    }

    @Override
    public Map<String, Object> getSumDataBy(String mediaId, BigDecimal discount, JSONArray accounts, String startDate, String endDate) {
        Map<String, Object> result = new HashMap<>();
        JSONObject after;
        JSONObject before;
        Long startDateNum = Long.parseLong(startDate.replace("-",""));
        Long anotherStartDateNum = Long.parseLong(DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, startDate, -1).replace("-",""));

        Long endDateNum = Long.parseLong(endDate.replace("-",""));
        Long anotherEndDateNum = Long.parseLong(DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, endDate, -1).replace("-",""));
        if (startDateNum.equals(endDateNum)) {
            after = accountAttributionInfoMapper.queryTodaySumReportBy(startDateNum, accounts);
            if (after == null) {
                return result;
            }
            before = accountAttributionInfoMapper.queryTodaySumByHour(anotherStartDateNum, after.getInteger("maxHour"), accounts);
            if (before == null) {
                before = after;
            }
        } else {
            after = accountAttributionInfoMapper.querySumByStartEndDate(endDateNum, startDateNum, accounts);
            if (after == null) {
                return result;
            }
            before = after;
        }
        return getSumLink(mediaId, discount, after, before);

    }

    @Override
    public Map<String, Object> getBytedanceSumDataBy(String mediaId, BigDecimal discount, JSONArray accounts, String startDate, String endDate) {
        Map<String, Object> result = new HashMap<>();
        JSONObject after;
        JSONObject before;
        Long startDateNum = Long.parseLong(startDate.replace("-",""));
        Long anotherStartDateNum = Long.parseLong(DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, startDate, -1).replace("-",""));

        Long endDateNum = Long.parseLong(endDate.replace("-",""));
        Long anotherEndDateNum = Long.parseLong(DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, endDate, -1).replace("-",""));
        if (startDateNum.equals(endDateNum)) {
            after = accountAttributionInfoMapper.queryBytedanceTodaySumReportBy(startDateNum, accounts);
            if (after == null) {
                return result;
            }
            before = accountAttributionInfoMapper.queryBytedanceTodaySumByHour(anotherStartDateNum, after.getInteger("maxHour"), accounts);
            if (before == null) {
                before = after;
            }
        } else {
            after = accountAttributionInfoMapper.queryBuytedanceSumByStartEndDate(endDateNum, startDateNum, accounts);
            if (after == null) {
                return result;
            }
            before = after;
        }
        return getBytedanceSumLink(mediaId, discount, after, before);

    }


    @Override
    public List<JSONObject> getChartDataBy(String mediaId, BigDecimal discount, JSONArray accounts, String startDate, String endDate) throws ParseException {
        List<JSONObject> result = new ArrayList<>();
        String filedAll = JsonResourceUtil.joinAllFiled(AccountReportConstants.getDicMapKs());
        Long startDateNum = Long.parseLong(startDate.replace("-",""));
        Long anotherStartDateNum = Long.parseLong(DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, startDate, -1).replace("-",""));

        Long endDateNum = Long.parseLong(endDate.replace("-",""));
        Long anotherEndDateNum = Long.parseLong(DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, endDate, -1).replace("-",""));
        if (startDateNum.equals(endDateNum)) {
            List<JSONObject> after = accountAttributionInfoMapper.queryTodayDetailReportBy(filedAll, startDateNum, accounts);
            List<JSONObject> before = accountAttributionInfoMapper.queryTodayDetailReportBy(filedAll, anotherStartDateNum, accounts);
            if (after.size() == 0) {
                return result;
            }
            if (before.size() == 0) {
                before = nullDataHandle();
            }
            List<JSONObject> afterDis = this.countDiscountCost(mediaId, discount, after);
            List<JSONObject> beforeDis = this.countDiscountCost(mediaId, discount, before);
            result = LinkUtils.getCompareDate(beforeDis, afterDis, "statHour");
        } else {
            List<JSONObject> after;
            //判断是不是日期间隔大于半年
            if (DateUtils.isMoreSixMonth(startDate, endDate)) {
                after = accountAttributionInfoMapper.queryDetailGroupMonthByDate(endDateNum, startDateNum, accounts);
            } else {
                after = accountAttributionInfoMapper.queryDetailByStartEndDate(endDateNum, startDateNum, accounts);
            }
            if (after == null) {
                return result;
            }
            result = this.countDiscountCost(mediaId, discount, after);
        }
        return result;
    }

    @Override
    public List<JSONObject> getBytedanceChartDataBy(String mediaId, BigDecimal discount, JSONArray accounts, String startDate, String endDate) throws ParseException {
        List<JSONObject> result = new ArrayList<>();
        String filedAll = JsonResourceUtil.joinAllFiled(AccountReportConstants.getDicMapKs());
        Long startDateNum = Long.parseLong(startDate.replace("-",""));
        Long anotherStartDateNum = Long.parseLong(DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, startDate, -1).replace("-",""));

        Long endDateNum = Long.parseLong(endDate.replace("-",""));
        Long anotherEndDateNum = Long.parseLong(DateUtils.getAnotherDay(SystemDateConstant.yyyy_MM_dd, endDate, -1).replace("-",""));
        if (startDateNum.equals(endDateNum)) {
            List<JSONObject> after = accountAttributionInfoMapper.queryBytedanceTodayDetailReportBy(filedAll, startDateNum, accounts);
            List<JSONObject> before = accountAttributionInfoMapper.queryBytedanceTodayDetailReportBy(filedAll, anotherStartDateNum, accounts);
            if (after.size() == 0) {
                return result;
            }
            if (before.size() == 0) {
                before = nullDataHandle();
            }
            List<JSONObject> afterDis = this.countDiscountCost(mediaId, discount, after);
            List<JSONObject> beforeDis = this.countDiscountCost(mediaId, discount, before);
            //result = LinkUtils.getBytedancewCompareDate(beforeDis, afterDis, "statHour");
            result = afterDis;
        } else {
            List<JSONObject> after;
            //判断是不是日期间隔大于半年
            if (DateUtils.isMoreSixMonth(startDate, endDate)) {
                after = accountAttributionInfoMapper.queryBytedanceDetailGroupMonthByDate(endDateNum, startDateNum, accounts);
            } else {
                after = accountAttributionInfoMapper.queryBytedanceDetailByStartEndDate(endDateNum, startDateNum, accounts);
            }
            if (after == null) {
                return result;
            }
            result = this.countDiscountCost(mediaId, discount, after);
        }
        return result;
    }


    //计算汇总数据环比
    private Map<String, Object> getSumLink(String mediaId, BigDecimal discount, JSONObject after, JSONObject before) {

        Map<String, Object> result = new HashMap<>();

        JSONObject costLink = new JSONObject();
        JSONObject discountCostLink = new JSONObject();
        JSONObject photoClickLink = new JSONObject();
        JSONObject photoShowLink = new JSONObject();
        JSONObject aClickLink = new JSONObject();

        costLink.put("cost", after.getBigDecimal("cost"));
        costLink.put("costSumLink", LinkUtils.countLink(after.getBigDecimal("cost"), before.getBigDecimal("cost")));
        if (mediaId.equals(CtopAdConstant.PLATFORM_TYPE_KUAISHOU)) {
            discountCostLink.put("discountCost", after.getBigDecimal("cost").divide(discount, 4, RoundingMode.HALF_UP));
            discountCostLink.put("discountCostLink", LinkUtils.countLink(after.getBigDecimal("cost").divide(discount, 4, RoundingMode.HALF_UP), before.getBigDecimal("cost").divide(discount, 4, RoundingMode.HALF_UP)));
        } else {
            discountCostLink.put("discountCost", after.getBigDecimal("cost").multiply(discount));
            discountCostLink.put("discountCostLink", LinkUtils.countLink(after.getBigDecimal("cost").multiply(discount), before.getBigDecimal("cost").multiply(discount)));
        }
        photoClickLink.put("photoClick", after.getBigDecimal("photoClick"));
        photoClickLink.put("photoClickLink", LinkUtils.countLink(after.getBigDecimal("photoClick"), before.getBigDecimal("photoClick")));
        photoShowLink.put("photoShow", after.getBigDecimal("photoShow"));
        photoShowLink.put("photoShowLink", LinkUtils.countLink(after.getBigDecimal("photoShow"), before.getBigDecimal("photoShow")));
        aClickLink.put("aClick", after.getBigDecimal("aClick"));
        aClickLink.put("aClickLink", LinkUtils.countLink(after.getBigDecimal("aClick"), before.getBigDecimal("aClick")));
        result.put("costLink", costLink);
        result.put("discountCostLink", discountCostLink);
        result.put("photoClickLink", photoClickLink);
        result.put("photoShowLink", photoShowLink);
        result.put("aClickLink", aClickLink);
        return result;
    }

    //计算汇总数据环比
    private Map<String, Object> getBytedanceSumLink(String mediaId, BigDecimal discount, JSONObject after, JSONObject before) {

        Map<String, Object> result = new HashMap<>();

        JSONObject costLink = new JSONObject();
        JSONObject discountCostLink = new JSONObject();
        JSONObject photoClickLink = new JSONObject();
        JSONObject photoShowLink = new JSONObject();
        JSONObject convertLink = new JSONObject();

        costLink.put("cost", after.getBigDecimal("cost"));
        costLink.put("costSumLink", LinkUtils.countLink(after.getBigDecimal("cost"), before.getBigDecimal("cost")));
        if (mediaId.equals(CtopAdConstant.PLATFORM_TYPE_KUAISHOU)) {
            discountCostLink.put("discountCost", after.getBigDecimal("cost").divide(discount, 4, RoundingMode.HALF_UP));
            discountCostLink.put("discountCostLink", LinkUtils.countLink(after.getBigDecimal("cost").divide(discount, 4, RoundingMode.HALF_UP), before.getBigDecimal("cost").divide(discount, 4, RoundingMode.HALF_UP)));
        } else {
            discountCostLink.put("discountCost", after.getBigDecimal("cost").divide(discount,2, RoundingMode.HALF_UP));
            discountCostLink.put("discountCostLink", LinkUtils.countLink(after.getBigDecimal("cost").divide(discount,2, RoundingMode.HALF_UP), before.getBigDecimal("cost").divide(discount,2, RoundingMode.HALF_UP)));
        }
        photoClickLink.put("photoClick", after.getBigDecimal("photoClick"));
        photoClickLink.put("photoClickLink", LinkUtils.countLink(after.getBigDecimal("photoClick"), before.getBigDecimal("photoClick")));
        photoShowLink.put("photoShow", after.getBigDecimal("photoShow"));
        photoShowLink.put("photoShowLink", LinkUtils.countLink(after.getBigDecimal("photoShow"), before.getBigDecimal("photoShow")));
        convertLink.put("convert", after.getBigDecimal("convert"));
        convertLink.put("convertLink", LinkUtils.countLink(after.getBigDecimal("convert"), before.getBigDecimal("convert")));
        result.put("costLink", costLink);
        result.put("discountCostLink", discountCostLink);
        result.put("photoClickLink", photoClickLink);
        result.put("photoShowLink", photoShowLink);
        result.put("convertLink", convertLink);
        return result;
    }

    //计算折后消耗
    private List<JSONObject> countDiscountCost(String mediaId, BigDecimal discount, List<JSONObject> data) {
        if (data.isEmpty()) {
            return data;
        }
        if (mediaId.equals(CtopAdConstant.PLATFORM_TYPE_KUAISHOU)) {
            data.forEach(it -> {
                it.put("discountCost", it.getBigDecimal("cost").divide(discount, 3, RoundingMode.HALF_UP));
            });
        } else {
            data.forEach(it -> {
                it.put("discountCost", it.getBigDecimal("cost").divide(discount, 2, RoundingMode.HALF_UP));
            });
        }
        return data;
    }

    //计算总计环比
    private JSONObject countTotal(JSONObject after, JSONObject before) {
        JSONObject jsonObject = new JSONObject();
        after.forEach((k, v) -> {
            //去除没法计算的字段
            if ("accountId".equals(k) || "authName".equals(k) || v.toString().contains("%") || before.getString(k).contains("%")) {
                jsonObject.put(k, "-");
            } else {
                jsonObject.put(k, (LinkUtils.countLink(after.getBigDecimal(k) == null ? BigDecimal.ZERO : after.getBigDecimal(k), before.getBigDecimal(k) == null ? BigDecimal.ZERO : before.getBigDecimal(k))).multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP) + "%");
            }
        });
        return jsonObject;
    }

    private List<JSONObject> nullDataHandle() {
        List<JSONObject> objectList = new ArrayList<>();
        JSONObject jsonObject;
        for (int i = 0; i < 24; i++) {
            jsonObject = new JSONObject();
            jsonObject.put("cost", 0);
            jsonObject.put("photoShow", 0);
            jsonObject.put("photoClick", 0);
            jsonObject.put("aClick", 0);
            jsonObject.put("statHour", i);
            objectList.add(jsonObject);
        }
        return objectList;
    }
}
