package org.jeecg.ctop.material.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.DateUtils;
import org.jeecg.ctop.material.constants.Check;
import org.jeecg.ctop.material.entity.vo.KuaiShouOperateGroupVo;
import org.jeecg.ctop.material.mapper.BytedanceAccountReportDailyDwMapper;
import org.jeecg.ctop.material.service.IBytedanceAccountReportDailyDwService;
import org.jeecg.ctop.material.service.support.DashboardQuerySupport;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class BytedanceAccountReportDailyDwServiceImpl implements IBytedanceAccountReportDailyDwService {

    @Resource
    private BytedanceAccountReportDailyDwMapper bytedanceAccountReportDailyDwMapper;

    @Resource
    private DashboardQuerySupport dashboardQuerySupport;

    @Override
    public JSONObject getTotalCharge(Map<String, Object> paramsMap) {
        JSONObject by = bytedanceAccountReportDailyDwMapper.getTotalCharge(paramsMap);
        Long count = bytedanceAccountReportDailyDwMapper.getYesterdayUploadNewMaterialCount(paramsMap);
        by.put("bytedanceCount", count);
        return by;
    }

    @Override
    public JSONObject getTrendCharge(String type, Long projectId, String startTime, String endTime) {
        Integer startTimeInt = DateUtils.getDateInteger(startTime);
        Integer endTimeInt = DateUtils.getDateInteger(endTime);
        boolean currentDayOnly = startTime.equals(endTime) && startTime.equals(DateUtils.formatDate(new Date()));

        List<JSONObject> today = null;
        List<JSONObject> yesterday = null;
        if ("1".equals(type)) {
            today = bytedanceAccountReportDailyDwMapper.getProjectNoByDays(startTimeInt, endTimeInt);
        } else if ("2".equals(type)) {
            today = bytedanceAccountReportDailyDwMapper.getAdvertiserNoByDays(startTimeInt, endTimeInt);
        } else if ("3".equals(type)) {
            if (currentDayOnly) {
                today = bytedanceAccountReportDailyDwMapper.getUnitNoByHours(startTimeInt);
            } else {
                today = bytedanceAccountReportDailyDwMapper.getUnitNoByDays(startTimeInt, endTimeInt);
            }
        } else {
            if (currentDayOnly) {
                today = bytedanceAccountReportDailyDwMapper.getHourCost(projectId, startTimeInt);
                yesterday = bytedanceAccountReportDailyDwMapper.getHourCost(projectId, DateUtils.getDateInteger(DateUtils.getLastDay(startTime, 1)));
            } else {
                today = bytedanceAccountReportDailyDwMapper.getDataCost(projectId, startTimeInt, endTimeInt);
                fillingDates(startTime, endTime, today);
                int days = DateUtils.dateDiff(startTime, endTime);
                String endTime2 = DateUtils.getLastDay(startTime, 1);
                String startTime2 = DateUtils.getLastDay(endTime2, days);
                yesterday = bytedanceAccountReportDailyDwMapper.getDataCost(projectId, DateUtils.getDateInteger(startTime2), DateUtils.getDateInteger(endTime2));
                fillingDates(startTime2, endTime2, yesterday);
            }
        }
        JSONObject data = new JSONObject();
        data.put("today", today);
        data.put("yesterday", yesterday);
        return data;
    }

    /**
     * 补充日期
     */
    private void fillingDates(String startTime, String endTime, List<JSONObject> today) {
        long dayNum = DateUtils.getDiscrepantDays(startTime, endTime) + 1;
        int size = today.size();
        if (dayNum - size != 0) {
            List<String> days = DateUtils.getDays(startTime, endTime);
            Set<String> existingDays = today.stream().map(item -> item.getString("time")).collect(Collectors.toSet());
            for (String day : days) {
                if (!existingDays.contains(day)) {
                    JSONObject obj = new JSONObject();
                    obj.put("time", day);
                    obj.put("cost", 0.00);
                    today.add(obj);
                }
            }
        }
    }

    @Override
    public Result<Object> getProjectReport(String category, Long projectId, String startTime, String endTime, String sortCode, String order, Integer pageSize, Integer pageNo, Boolean allData) throws Exception {
        if (Check.isNull(order)) {
            order = "DESC";
        }
        if (Check.isNull(sortCode)) {
            sortCode = "cost";
        }
        Integer startTimeInt = DateUtils.getDateInteger(startTime);
        Integer endTimeInt = DateUtils.getDateInteger(endTime);
        //当前小时
        Integer nowHour = DateUtils.getNowHour();
        //当天日期
        String today = DateUtils.formatDate(new Date());
        List<JSONObject> data = null;
        if (startTime.equals(endTime) && today.equals(startTime)) {
            if (!Boolean.TRUE.equals(allData)) {
                PageHelper.startPage(pageNo, pageSize, false);
            }
            data = bytedanceAccountReportDailyDwMapper.getProjectToDayReport(category, projectId, startTimeInt, nowHour, sortCode, order);
        } else {
            int days = DateUtils.dateDiff(startTime, endTime) + 1;
            //上阶段时间
            Integer lastStart = DateUtils.getDateInteger(DateUtils.getLastDay(startTime, days));
            Integer lastEnd = DateUtils.getDateInteger(DateUtils.getLastDay(endTime, days));
            if (!Boolean.TRUE.equals(allData)) {
                PageHelper.startPage(pageNo, pageSize, false);
            }
            data = bytedanceAccountReportDailyDwMapper.getProjectMoreDaysReport(category, projectId, startTimeInt, endTimeInt, lastStart, lastEnd, sortCode, order);
        }
        PageInfo<JSONObject> page = new PageInfo<>(data);
        return Result.OK(page);
    }

    @Override
    public Result<Object> getOperateInfo(String startTime, String endTime) {
        try {
            //当前小时
            Integer hour = DateUtils.getNowHour();
            //当天日期
            String nowDateStr = DateUtils.formatDate(new Date());
            Long nowDate = Long.valueOf(DateUtils.getDateInteger(nowDateStr));

            Long startDate = Long.valueOf(DateUtils.getDateInteger(startTime));
            Long entDate = Long.valueOf(DateUtils.getDateInteger(endTime));

            //开始日期前一天
            String lastDay = DateUtils.getLastDay(startTime, 1);
            //相差天数，同一天为 0
            int days = DateUtils.dateDiff(startTime, endTime);
            //上阶段时间
            Long lastTimeEnd = Long.valueOf(DateUtils.getDateInteger(lastDay));
            Long lastTimeStart = Long.valueOf(DateUtils.getDateInteger(DateUtils.getLastDay(lastDay, days)));

            List<String> userIds = dashboardQuerySupport.getAllOperationUserIds("1");
            List<JSONObject> list = new ArrayList<>();
            if (startTime.equals(endTime) && startTime.equals(nowDateStr)) {
                list = bytedanceAccountReportDailyDwMapper.getToutiaoOperateInfoHourly(hour, startDate, entDate, lastTimeEnd, lastTimeStart, userIds);
            } else {
                list = bytedanceAccountReportDailyDwMapper.getToutiaoOperateInfo(startDate, entDate, lastTimeEnd, lastTimeStart, userIds);
            }
            PageInfo<JSONObject> pageInfo = new PageInfo<>(list);
            return Result.successMsg("查询成功。", pageInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.errorMsg("查询失败了。");
    }

    @Override
    public Result<Object> getOperateGroupInfo(String startTime, String endTime) {
        try {
            //当前小时
            Integer hour = DateUtils.getNowHour();
            //当天日期
            String nowDateStr = DateUtils.formatDate(new Date());
            Long nowDate = Long.valueOf(DateUtils.getDateInteger(nowDateStr));

            Long startDate = Long.valueOf(DateUtils.getDateInteger(startTime));
            Long entDate = Long.valueOf(DateUtils.getDateInteger(endTime));

            //开始日期前一天
            String lastDay = DateUtils.getLastDay(startTime, 1);
            //相差天数，同一天为 0
            int days = DateUtils.dateDiff(startTime, endTime);
            //上阶段时间
            Long lastTimeEnd = Long.valueOf(DateUtils.getDateInteger(lastDay));
            Long lastTimeStart = Long.valueOf(DateUtils.getDateInteger(DateUtils.getLastDay(lastDay, days)));

            List<JSONObject> list = new ArrayList<>();
            List<KuaiShouOperateGroupVo> operationManagerList = dashboardQuerySupport.getOperationManagers("touTiaoOperationManager");
            List<String> managerIds = operationManagerList.stream().map(KuaiShouOperateGroupVo::getUserId).collect(Collectors.toList());
            Map<String, String> managerNameMap = operationManagerList.stream().collect(Collectors.toMap(KuaiShouOperateGroupVo::getUserId, KuaiShouOperateGroupVo::getRealname, (left, right) -> left));
            if (managerIds.isEmpty()) {
                return Result.successMsg("查询成功。", new PageInfo<>(list));
            }
            if (startTime.equals(endTime) && startTime.equals(nowDateStr)) {
                list = bytedanceAccountReportDailyDwMapper.getToutiaoOperateGroupInfoHourlyBatch(managerIds, hour, startDate, entDate, lastTimeEnd, lastTimeStart);
            } else {
                list = bytedanceAccountReportDailyDwMapper.getToutiaoOperateGroupInfoBatch(managerIds, startDate, entDate, lastTimeEnd, lastTimeStart);
            }
            for (JSONObject row : list) {
                row.put("realname", managerNameMap.get(row.getString("userId")));
                double totalCost = getDouble(row, "totalCost");
                double lastCost = getDouble(row, "lastCost");
                int operationNum = row.getInteger("operationNum") == null ? 0 : row.getInteger("operationNum");
                long accountNum = getLong(row, "accountNum");
                row.put("yearOnYearCost", lastCost == 0D ? "0%" : new BigDecimal((totalCost - lastCost) / lastCost * 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "%");
                row.put("averageDayCost", new BigDecimal(totalCost / (days + 1)).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
                row.put("averagePeopleCost", new BigDecimal(operationNum == 0 ? 0D : totalCost / operationNum).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
                row.put("averageAccountCost", new BigDecimal(accountNum == 0 ? 0D : totalCost / accountNum).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
            }
            PageInfo<JSONObject> pageInfo = new PageInfo<>(list);
            return Result.successMsg("查询成功。", pageInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.errorMsg("查询失败了。");
    }

    private Map<String, JSONObject> toMetricMap(List<JSONObject> rows) {
        if (rows == null || rows.isEmpty()) {
            return Collections.emptyMap();
        }
        return rows.stream()
                .filter(item -> item != null && item.getString("userId") != null)
                .collect(Collectors.toMap(item -> item.getString("userId"), item -> item, (left, right) -> left));
    }

    private long getLong(JSONObject row, String key) {
        Long value = row.getLong(key);
        return value == null ? 0L : value;
    }

    private double getDouble(JSONObject row, String key) {
        Double value = row.getDouble(key);
        return value == null ? 0D : value;
    }

}
