package com.yeejoin.amos.knowledgebase.face.service;


import com.yeejoin.amos.knowledgebase.face.model.KnowlegeStatisticsRecordModel;
import com.yeejoin.amos.knowledgebase.face.orm.dao.StatisticsRecordMapper;
import com.yeejoin.amos.knowledgebase.face.orm.entity.KnowlegeStatisticsRecord;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.typroject.tyboot.core.rdbms.service.BaseService;

import java.util.*;


/**
 * <p>
 * 标签分组 服务类
 * </p>
 *
 * @author 子杨
 * @since 2020-08-05
 */
@Component
public class StatisticsRecordService extends BaseService<KnowlegeStatisticsRecordModel, KnowlegeStatisticsRecord, StatisticsRecordMapper> {

    /*@Autowired
    private DocContentService docContentService;

    private final Logger logger = LogManager.getLogger(StatisticsRecordService.class);

    *//**
     * 灾情标记
     *//*
    public static final String TAG_NAME_TIME = "时间";
    public static final String STATISTICS_DISASTER_COUNT = "DISASTER_RECORD";

    *//**
     * 燃烧物质分类
     *//*
    public static final String TAG_NAME_BURNING = "燃烧物质";
    public static final String STATISTICS_BURNING_CATEGORY = "BURNING_RECORD";

    *//**
     * 参战车辆统计
     *//*
    public static final String TAG_NAME_POWER = "参战车辆";
    public static final String STATISTICS_POWER_SUM = "POWER_RECORD";

    *//**
     * 伤亡人数统计
     *//*
    public static final String TAG_NAME_CASUALTIES = "人员伤亡情况 含亡人";
    public static final String STATISTICS_CASUALTIES_SUM = "CASUALTIES_RECORD";

    *//**
     * 灭火药剂统计
     *//*
    public static final String TAG_NAME_EXTINGUISHING = "使用的灭火药剂数量";
    public static final String STATISTICS_EXTINGUISHING_SUM = "EXTINGUISHING_RECORD";

    *//**
     * 过火面积统计
     *//*
    public static final String TAG_NAME_AREA = "过火面积";
    public static final String STATISTICS_AREA_COUNT = "FIRE_AREA_RECORD";

    *//**
     * 到场时间分类
     *//*
    public static final String TAG_NAME_PICKUP = "接警时间";
    public static final String TAG_NAME_PRESENT = "到场时间";
    public static final String STATISTICS_PRESENT_CATEGORY = "PRESENT_TIME_RECORD";


    public static final String DATE_GROUP_BY_DAY = "day";
    public static final String DATE_GROUP_BY_MONTH = "month";

    @Value("${diy-config.report.record-data}")
    private boolean needRecord;

    *//** 根据文档标签添加对应的记录 *//*
    private void addRecordWithDocValueTag(List<KnowledgeTagInstanceModel> docTags, Long docSeq) {
        //找出预定义的所有标签
        Map<Object, KnowledgeTagInstanceModel> tagMap = Bean.listToMap(docTags, "tagName", KnowledgeTagInstanceModel.class);
        KnowledgeTagInstanceModel tagTime = tagMap.get(TAG_NAME_TIME);
        if (ValidationUtil.isEmpty(tagTime)) {
            return;
        }
        Object timeObj = getValueFromTag(tagTime);
        if (ValidationUtil.isEmpty(timeObj) || !(timeObj instanceof Date)) {
            return;
        }
        Date disasterTime = (Date) timeObj;
        //记录灾情
        insertSumTypeRecord(docSeq, disasterTime, STATISTICS_DISASTER_COUNT, 1.0, 1);
        //记录燃烧物质
        KnowledgeTagInstanceModel tagBurning = tagMap.get(TAG_NAME_BURNING);
        if (!ValidationUtil.isEmpty(tagBurning)) {
            insertCategoryTypeRecord(docSeq, disasterTime, STATISTICS_BURNING_CATEGORY, getValueFromTag(tagBurning));
        }
        //记录参战车辆
        KnowledgeTagInstanceModel tagPower = tagMap.get(TAG_NAME_POWER);
        if (!ValidationUtil.isEmpty(tagPower)) {
            insertSumTypeRecord(docSeq, disasterTime, STATISTICS_POWER_SUM, getValueFromTag(tagPower), 1);
        }
        //记录伤亡人数
        KnowledgeTagInstanceModel tagCasualties = tagMap.get(TAG_NAME_CASUALTIES);
        if (!ValidationUtil.isEmpty(tagCasualties)) {
            insertSumTypeRecord(docSeq, disasterTime, STATISTICS_CASUALTIES_SUM, getValueFromTag(tagCasualties), 1);
        }
        //记录灭火药剂数量
        KnowledgeTagInstanceModel tagExtinguishing = tagMap.get(TAG_NAME_EXTINGUISHING);
        if (!ValidationUtil.isEmpty(tagExtinguishing)) {
            insertSumTypeRecord(docSeq, disasterTime, STATISTICS_EXTINGUISHING_SUM, getValueFromTag(tagExtinguishing), 1);
        }
        //记录过火面积
        KnowledgeTagInstanceModel tagArea = tagMap.get(TAG_NAME_AREA);
        if (!ValidationUtil.isEmpty(tagArea)) {
            insertSumTypeRecord(docSeq, disasterTime, STATISTICS_AREA_COUNT, getValueFromTag(tagArea), 1);
        }
        //记录到场时间
        KnowledgeTagInstanceModel tagPickup = tagMap.get(TAG_NAME_PICKUP);
        KnowledgeTagInstanceModel tagPresent = tagMap.get(TAG_NAME_PRESENT);
        if (!ValidationUtil.isEmpty(tagPickup) && !ValidationUtil.isEmpty(tagPresent)) {
            Object pickTimeObj = getValueFromTag(tagPickup);
            Object presentTimeObj = getValueFromTag(tagPresent);
            if (!ValidationUtil.isEmpty(pickTimeObj) && pickTimeObj instanceof Date
                    && !ValidationUtil.isEmpty(presentTimeObj) && presentTimeObj instanceof Date) {
                long presentTimeByMinute = (long) Math.ceil((((Date) presentTimeObj).getTime() - ((Date) pickTimeObj).getTime()) / 1000.0 / 60.0);
                insertCategoryTypeRecord(docSeq, disasterTime, STATISTICS_PRESENT_CATEGORY, presentTimeByMinute);
            }
        }
    }

    *//** 获取标签值 *//*
    private Object getValueFromTag(KnowledgeTagInstanceModel tag) {
        if (ValidationUtil.isEmpty(tag)
                || !ValidationUtil.equals(tag.getTagType(), TagService.TAG_TYPE_VALUE)
                || ValidationUtil.isEmpty(tag.getTagValues())) {
            return null;
        }
        String fieldName = tag.getTagValues().get(0).getFieldName();
        String tagValue = tag.getTagValues().get(0).getTagValue();
        if (ValidationUtil.isEmpty(fieldName)
                || ValidationUtil.isEmpty(tagValue)) {
            return null;
        }
        switch (fieldName) {
            case TagValueService.VALUE_TAG_FIELD_DATE_H:
                try {
                    return DateUtil.formatStringToDate(tagValue, null);
                } catch (Exception e) {
                    logger.error("报表统计：时间格式标签值解析出错");
                    return null;
                }
            case TagValueService.VALUE_TAG_FIELD_SINGLEVALUE:
                try {
                    return Double.parseDouble(tagValue);
                } catch (Exception e) {
                    logger.error("报表统计：数字格式标签值解析出错");
                    return null;
                }
            case TagValueService.VALUE_TAG_FIELD_TEXT:
                return tagValue;
            default:
                return null;
        }
    }

    *//** 插入分类统计记录 *//*
    private void insertCategoryTypeRecord(Long docSeq, Date disasterTime, String recordName, Object category) {
        KnowlegeStatisticsRecordModel recordModel = new KnowlegeStatisticsRecordModel();
        recordModel.setDocSeq(docSeq);
        recordModel.setDisasterTime(disasterTime);
        recordModel.setRecordName(recordName);
        recordModel.setCategoryValue(String.valueOf(category));
        recordModel.setValueWeight(1);
        recordModel.setCountValue(1L);
        this.createWithModel(recordModel);
    }


    *//** 插入数量统计记录 *//*
    private void insertSumTypeRecord(Long docSeq, Date disasterTime, String recordName, Object numObj, Integer weight) {
        if (!ValidationUtil.isEmpty(numObj) && numObj instanceof Double) {
            Long num = ((Double) numObj).longValue();
            KnowlegeStatisticsRecordModel recordModel = new KnowlegeStatisticsRecordModel();
            recordModel.setDocSeq(docSeq);
            recordModel.setDisasterTime(disasterTime);
            recordModel.setRecordName(recordName);
            recordModel.setCountValue(num);
            recordModel.setValueWeight(weight);
            this.createWithModel(recordModel);
        }
    }

    *//**
     * 根据文档id删除相关记录
     *//*
    public void deleteRecordsByDocIds(List<KnowledgeDocContentModel> docs) {
        if (!ValidationUtil.isEmpty(docs)) {
            Set ids = Bean.listToMap(docs, "sequenceNbr", KnowledgeDocContentModel.class).keySet();
            QueryWrapper<KnowlegeStatisticsRecord> wrapper = new QueryWrapper<>();
            wrapper.in("doc_seq", ids);
            this.getBaseMapper().delete(wrapper);
        }
    }

    *//**
     * 初始化统计数据记录
     *
     * @return
     *//*
    @Transactional(rollbackFor = {Exception.class, BaseException.class})
    public boolean init() {
        this.getBaseMapper().deleteAll();
        //扫描所有已发布文档相关的统计型标签
        QueryWrapper<KnowledgeDocContent> wrapper = new QueryWrapper<>();
        wrapper.eq("doc_status", DocContentService.DOC_STATUS_PUBLISHED);
        int count = docContentService.count(wrapper);
        int finishNmu = 0;
        int current = 0;
        while (count > finishNmu) {
            Page page = new Page(current++, 30);
            IPage resPage = docContentService.page(page, wrapper);
            List<KnowledgeDocContent> records = resPage.getRecords();
            Set ids = Bean.listToMap(records, "sequenceNbr", KnowledgeDocContent.class).keySet();
            saveRecordsByDocIds(ids);
            finishNmu += records.size();
        }
        return true;
    }

    public boolean addDocRecords(List<KnowledgeDocContentModel> docs) {
        if (!ValidationUtil.isEmpty(docs)) {
            Set ids = Bean.listToMap(docs, "sequenceNbr", KnowledgeDocContentModel.class).keySet();
            saveRecordsByDocIds(ids);
        }
        return true;
    }

    private void saveRecordsByDocIds(Collection ids) {
        if (!needRecord) {
            return;
        }
        for (Object id : ids) {
            KnowledgeDocContentModel docContentModel = docContentService.queryOneDocDetail((Long) id);
            if (ValidationUtil.isEmpty(docContentModel)) {
                continue;
            }
            addRecordWithDocValueTag(docContentModel.getDocTags(), docContentModel.getSequenceNbr());
        }
    }

    *//**
     * 查询灾情统计/同比/环比
     *
     * @return
     *//*
    public Map<String, Object> selectDisasterCount() {
        return this.getBaseMapper().selectDisasterCount();
    }

    public List<Map<String, Object>> selectCategoryByName(String recordName) {
        return this.getBaseMapper().selectCategoryByName(recordName);
    }

    *//**
     * 分类汇总
     *//*
    public List<Map<String, Object>> selectCountByTypeAndDateRange(String dateType, String dateRangeLeft, String dateRangeRight, String recordName) {
        Map<String, Object> queryMap = new HashMap<>();
        switch (dateType) {
            case DATE_GROUP_BY_MONTH:
                queryMap.put("format", "%Y-%m");
                break;
            default:
                queryMap.put("format", "%Y-%m-%d");
                break;
        }
        if(!ValidationUtil.isEmpty(dateRangeLeft)){
            try {
                queryMap.put("dateRangeLeft", DateUtil.formatStringToDate(dateRangeLeft, null));
            } catch (Exception e) {
                throw new BadRequest("时间参数格式有误");
            }
        }
        if(!ValidationUtil.isEmpty(dateRangeRight)){
            try {
                queryMap.put("dateRangeRight", DateUtil.formatStringToDate(dateRangeRight, null));
            } catch (Exception e) {
                throw new BadRequest("时间参数格式有误");
            }
        }
        queryMap.put("recordName", recordName);
        return this.getBaseMapper().selectCountByNameAndDateRange(queryMap);
    }*/
	public Map<String, Object> tagStatistics(String tag, Date startDate, Date endDate, String mode) {
		endDate = getLastDayOfMonth(endDate);
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Map<String, Object> map = new HashMap<String, Object>();
		if ("year".equals(mode)) {
			list = this.baseMapper.tagStatisticsYear(tag, startDate, endDate);
		} else {
			list = this.baseMapper.tagStatisticsMonth(tag, startDate, endDate);
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(endDate);
		int year = cal.get(Calendar.YEAR);
		list.forEach(i -> {
			if ("year".equals(mode)) {
				if (i.get("date") != null && Integer.valueOf((String) (i.get("date"))) <= year) {
					map.put((String) i.get("date"), i.get("datas"));
				}
			} else {
				map.put((String) i.get("date"), i.get("datas"));
			}
		});
		return map;
	}

	public Map<String, Object> docStatistics(String categoryName, Date startDate, Date endDate, String mode) {
		endDate = getLastDayOfMonth(endDate);
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Map<String, Object> map = new HashMap<String, Object>();
		if ("year".equals(mode)) {
			list = this.baseMapper.docStatisticsYear(categoryName, startDate, endDate);
		} else {
			list = this.baseMapper.docStatisticsMonth(categoryName, startDate, endDate);
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(endDate);
		int year = cal.get(Calendar.YEAR);
		list.forEach(i -> {
			if ("year".equals(mode)) {
				if (i.get("date") != null && Integer.valueOf((String) (i.get("date"))) <= year) {
					map.put((String) i.get("date"), i.get("datas"));
				}
			} else {
				map.put((String) i.get("date"), i.get("datas"));
			}
		});
		return map;
	}

	public Map<String, Object> tagChartStatistics(String tag, Date startDate, Date endDate, List<Integer> split,
			String unit) {
		endDate = getLastDayOfMonth(endDate);
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Map<String, Object> map = new HashMap<String, Object>();
		StringBuffer sb = new StringBuffer();
		sb.append("elt(interval(ktv.TAG_VALUE");
		for (int s : split) {
			sb.append(",").append(s);
		}
		sb.append(")");
		String last = "";
		for (int s : split) {
			if (StringUtils.isNotEmpty(last)) {
				sb.append(",'").append(last).append("-").append(s).append(unit).append("'");
			}
			last = String.valueOf(s);
		}
		sb.append(",'").append(last).append(unit).append("以上'").append(")");
		// String sql="elt(interval(ktv.TAG_VALUE,0, 5, 10, 40), 'less100', '100to500',
		// '500to1000', 'more1000K')";
		list = this.baseMapper.tagChartStatistics(tag, startDate, endDate, sb.toString());
		list.forEach(i -> {
			if (i.get("level") != null) {
				map.put((String) i.get("level"), i.get("datas"));
			}
		});
		return map;
	}

	public Map<String, Object> tagTimeChartStatistics(Date startDate, Date endDate, List<Integer> split, String unit) {
		endDate = getLastDayOfMonth(endDate);
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Map<String, Object> map = new HashMap<String, Object>();
		StringBuffer sb = new StringBuffer();
		sb.append("elt(interval(kdc.TAG_VALUE");
		for (int s : split) {
			sb.append(",").append(s);
		}
		sb.append(")");
		String last = "";
		for (int s : split) {
			if (StringUtils.isNotEmpty(last)) {
				sb.append(",'").append(last).append("-").append(s).append(unit).append("'");
			}
			last = String.valueOf(s);
		}
		sb.append(",'").append(last).append(unit).append("以上'").append(")");
		// String sql="elt(interval(ktv.TAG_VALUE,0, 5, 10, 40), 'less100', '100to500',
		// '500to1000', 'more1000K')";
		list = this.baseMapper.tagTimeChartStatistics(startDate, endDate, sb.toString());
		list.forEach(i -> {
			if (i.get("level") != null) {
				map.put((String) i.get("level"), i.get("datas"));
			}
		});
		return map;
	}

	public Map<String, Object> docChartStatistics(Date startDate, Date endDate) {
		endDate = getLastDayOfMonth(endDate);
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Map<String, Object> map = new HashMap<String, Object>();
		list = this.baseMapper.docChartStatistics(startDate, endDate);
		list.forEach(i -> {
			if (i.get("categoryName") != null) {
				map.put((String) i.get("categoryName"), i.get("datas"));
			}
		});
		return map;
	}
	
	public Map<String, Object> docBurnChartStatistics(Date startDate, Date endDate) {
		endDate = getLastDayOfMonth(endDate);
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Map<String, Object> map = new HashMap<String, Object>();
		list = this.baseMapper.docBurnChartStatistics(startDate, endDate);
		list.forEach(i -> {
			if (i.get("level") != null) {
				map.put((String) i.get("level"), i.get("datas"));
			}
		});
		return map;
	}

	private static Date getLastDayOfMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		// 获取某月最大天数
		int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
		// 设置日历中月份的最大天数
		cal.set(Calendar.DAY_OF_MONTH, lastDay);
		return cal.getTime();
	}
}
