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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ctc.wstx.util.StringUtil;
import com.yeejoin.amos.knowledgebase.face.model.KnowledgeDocContentModel;
import com.yeejoin.amos.knowledgebase.face.model.KnowledgeTagInstanceModel;
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.KnowledgeDocContent;
import com.yeejoin.amos.knowledgebase.face.orm.entity.KnowlegeStatisticsRecord;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.foundation.exception.BaseException;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.foundation.utils.DateUtil;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.text.SimpleDateFormat;
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> 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;
	}

	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();
	}
}
