package org.jeecg.modules.stm.metric.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 
 
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;

import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.jeecg.modules.stm.base.domain.service.IStDomainService;
import org.jeecg.modules.stm.metric.entity.MetricMonitorSet;
import org.jeecg.modules.stm.metric.entity.MetricStatReport;
import org.jeecg.modules.stm.metric.entity.MetricStatSet;
import org.jeecg.modules.stm.metric.service.IMetricMonitorSetService;
import org.jeecg.modules.stm.metric.service.IMetricStatReportService;
import org.jeecg.modules.stm.metric.service.IMetricStatSetService;
import org.jeecg.modules.stm.utils.CreateWordUtil;

import jakarta.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;



@RestController
@RequestMapping("/metric/metricStatReport")
@Slf4j
public class MetricStatReportController extends JeecgController<MetricStatReport, IMetricStatReportService> {
	@Autowired
	private IMetricStatReportService metricStatReportService;
	@Autowired
	private IMetricStatSetService metricStatSetService;
	@Autowired
	private IStDomainService stDomainService;
	@Autowired
	private ISysDepartService sysDepartService;
	@Autowired
	private IMetricMonitorSetService metricMonitorSetService;
	@Autowired
	private ISysDictService sysDictService;

	@Value(value = "${jeecg.path.upload}")
	private String uploadpath;


	@GetMapping(value = "/list")
	public Result<IPage<MetricStatReport>> queryPageList(MetricStatReport metricStatReport,
					   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
					   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
					   HttpServletRequest req) {
		QueryWrapper<MetricStatReport> queryWrapper = QueryGenerator.initQueryWrapper(metricStatReport, req.getParameterMap());
		Page<MetricStatReport> page = new Page<MetricStatReport>(pageNo, pageSize);
		IPage<MetricStatReport> pageList = metricStatReportService.page(page, queryWrapper);
		return Result.OK(pageList);
	}
	

	@AutoLog(value = "监测报告-添加")

	//@RequiresPermissions("metric:metric_stat_report:add")
	@PostMapping(value = "/add")
	public Result<String> add(@RequestBody MetricStatReport metricStatReport) {
		int statDuration = metricStatReport.getTp(); //获取报告类型
		List<MetricStatSet> metricStatSetList = getMetricStatSet(statDuration); //获取报告模板
		if (metricStatSetList.isEmpty()) {
			return Result.OK("没有查询到配置信息！");
		}
		MetricStatSet metricStatSet0 = metricStatSetList.get(0);  // 每种类型的报告只有一个模板
		//根据 statMethod 统计方法 1 按照领域分类 2 按照类别分类
		int statMethod = metricStatReport.getStatMethod();
		List<Map<String, Object>> statData = getStatData(metricStatReport, statMethod);

		if (statData.isEmpty()) {
			return Result.OK("没有要统计的数据！");
		}

		CreateWordUtil createWordUtil = new CreateWordUtil();
		createWordUtil.ini();
		// 设置封面
		populateReportHeader(createWordUtil, metricStatReport);
		//获取统计周期名称
		String durationName = getDurationName(statDuration);
		//统计指标总数
		Integer mtrcNum = getMetricStaTotal(statDuration);
		//前次统计指标总数
		int beforeNum = getBeforMtricNum(statDuration);

		// 统计图的数据
		Map<String,List<String>>  nameAndCodeMap=  getStatDomainData(statData);
		List<String>  codes = nameAndCodeMap.get("codes");
		List<String>  names = nameAndCodeMap.get("names");

		if(codes.size()>0){
			Map<String, Integer[]> chartMap = metricStatReportService.list2Map(codes, statData);
			createWordUtil.addChart("overallStaChart", null, chartMap,names);
		}
		//整体情况
		Map<String, Object> overallStaData = metricStatReportService.list2RiskStat(statData,mtrcNum);
		Integer totalNum= mtrcNum = (Integer)overallStaData.get("total");
		String strOverallDes = metricStatReportService.getOverallDes(statData,mtrcNum,beforeNum,durationName);
		createWordUtil.addText("overallDes",strOverallDes);

		//具体信息情况
		populateOverallStatistics(createWordUtil, overallStaData, durationName, metricStatSet0);
		List<Map<String,Object>> statDetailList = metricStatReportService.queryMetricStatDetail(metricStatReport);
		List<Map<String, Object>> mtrcStatList = populateMetricDetails(names,codes,statDetailList, statMethod);
		createWordUtil.addAreasDetail("mtrc_stat_detail", mtrcStatList);
		addSuggestions(createWordUtil, overallStaData);

		try {
			String fileName = getFileName(metricStatReport.getSubtitle(), getCurrentDateRange(metricStatReport));
			String newFileName = createWordUtil.createFile(uploadpath, fileName);
			saveReport(mtrcNum,metricStatReport, newFileName, overallStaData);
		} catch (Exception e) {
			e.printStackTrace();
			return Result.error("服务器异常，创建失败，请重试！");
		}

		return Result.OK("创建成功！");
	}


	@AutoLog(value = "监测报告-编辑")

	//@RequiresPermissions("metric:metric_stat_report:edit")
	@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
	public Result<String> edit(@RequestBody MetricStatReport metricStatReport) {
		metricStatReportService.updateById(metricStatReport);
		return Result.OK("编辑成功!");
	}

	@AutoLog(value = "监测报告-通过id删除")

	//@RequiresPermissions("metric:metric_stat_report:delete")
	@DeleteMapping(value = "/delete")
	public Result<String> delete(@RequestParam(name="id",required=true) String id) {
		metricStatReportService.removeById(id);
		return Result.OK("删除成功!");
	}
	

	@AutoLog(value = "监测报告-批量删除")

	//@RequiresPermissions("metric:metric_stat_report:deleteBatch")
	@DeleteMapping(value = "/deleteBatch")
	public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
		this.metricStatReportService.removeByIds(Arrays.asList(ids.split(",")));
		return Result.OK("批量删除成功!");
	}
	


	@GetMapping(value = "/queryById")
	public Result<MetricStatReport> queryById(@RequestParam(name="id",required=true) String id) {
		MetricStatReport metricStatReport = metricStatReportService.getById(id);
		if(metricStatReport==null) {
			return Result.error("未找到对应数据");
		}
		return Result.OK(metricStatReport);
	}


	private String arabic2Chinese(int k) {
		String[] ary = {
			"一","二","三","四","五","六","七","八","九", "十",
			"十一","十二","十三","十四","十五","十六","十七","十八","十九","二十",
			"二十一","二十二","二十三","二十四","二十五","二十六","二十七","二十八","二十九","三十",
			"三十一","三十二","三十三","三十四","三十五","三十六","三十七","三十八","三十九", "四十",
			"四十一","四十二","四十三","四十四","四十五","四十六","四十七","四十八","四十九", "五十",
			"五十一","五十二","五十三","五十四","五十五","五十六","五十七","五十八","五十九","六十",
			"六十一","六十二","六十三","六十四","六十五","六十六","六十七","六十八","六十九","七十",
			"七十一","七十二","七十三","七十四","七十五","七十六","七十七","七十八","七十九"
		};
		if(k>100) return ""+k;
        return ary[k];
	}

	private String getStatResult(MetricStatSet metricStatSet,Object statData) {
		Map<String,Object> mapData = (Map<String,Object>)statData;
		float val = mapData.get("low")==null?0f:Float.parseFloat(mapData.get("low").toString());
		if(val>=metricStatSet.getLevel1()){
			return  "优秀";
		} else if(val>=metricStatSet.getLevel2()) {
			return "良好";
		} else if(val>=metricStatSet.getLevel3()) {
			return "一般";
		} else if(val>=metricStatSet.getLevel4()) {
			return "较差";
		} else if(val>=metricStatSet.getLevel5()) {
			return "差";
		} else  {
			return "极差";
		}
	}

	private String getRistLevelName(Object val) {
		int k = val==null?0:Integer.parseInt(val.toString());
		String[] ary = {"其他","正常","预警","干预"};
		return ary[k];
	}

	private String getDeparatName(String ids) {
		if(ids==null||ids.isEmpty()) return "";
		StringBuffer sb = new StringBuffer();
		String[] idAry = ids.split(",");
		QueryWrapper<SysDepart> queryWrapper = new QueryWrapper<>();
		queryWrapper.in("id",idAry);
		List<SysDepart> list = sysDepartService.list(queryWrapper);
		for(int i=0;i<list.size();i++){
			sb.append(",").append(list.get(i).getDepartName());
		}
		if(sb.length()<1) return "";
		return sb.substring(1);
	}

	private String getCurrentDate(Date date) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日");
		String formattedDate = dateFormat.format(date);
		return formattedDate;
	}

	private String getDurationName(int k){
		String[] ary = {"","日","周","月","季度","半年","年"};
		return ary[k];
	}

    // 得到上一个统计周期指标数
	private int getBeforMtricNum(int tp){
		QueryWrapper<MetricStatReport> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("tp",tp).orderByDesc("create_time").last("limit 1");
		MetricStatReport mr= metricStatReportService.getOne(queryWrapper);
		if(mr!=null) {
			return mr.getStatTargetNum()==null?0:mr.getStatTargetNum();
		}
		return 0;
	}

	// 得到本周期指标数
	private int getCurrMtricNum(int tp){
		QueryWrapper<MetricMonitorSet> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("coll_freq",tp).eq("mtrc_tp",1);
		Number count = metricMonitorSetService.getBaseMapper().selectCount(queryWrapper);
		return count.intValue();
	}

	// 得到文件名称
	private String getFileName(String title,String strDate){
      StringBuffer sb = new StringBuffer();
	  sb.append(title).append("-").append(strDate).append(".docx");
	  return sb.toString();
	}

	private Map<String, List<String>> getStatDomainData(List<Map<String, Object>> datas) {
		List<String> listName = new ArrayList<>();
		List<String> listCode = new ArrayList<>();
		Map<String, List<String>> retMap = new HashMap<>();
		int total = 0;
		Set<String> seenCodes = new HashSet<>();

		for (Map<String, Object> tmpMap : datas) {
			Object code = tmpMap.get("code");
			Object name = tmpMap.get("name");
			if (code == null || name == null) {
				continue;
			}
			if (seenCodes.add(code.toString())) {
				listName.add(name.toString());
				listCode.add(code.toString());
			}
		}
		retMap.put("codes", listCode);
		retMap.put("names", listName);
		return retMap;
	}

	private int getMetricStaTotal(Integer statDurtion) {
		QueryWrapper<MetricMonitorSet> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("mtrc_tp",1).eq("coll_freq",statDurtion);
		long total = metricMonitorSetService.count(queryWrapper);
		return (int)total;
	}

	private List<MetricStatSet> getMetricStatSet(int statDuration) {
		QueryWrapper<MetricStatSet> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("tp", statDuration);
		return metricStatSetService.list(queryWrapper);
	}

	private List<Map<String, Object>> getStatData(MetricStatReport metricStatReport,int statMethod) {

		return (statMethod == 1)
				? metricStatReportService.queryMetricStatByDomain(metricStatReport)
				: metricStatReportService.queryMetricStatByMtricClass(metricStatReport);
	}

	private void populateReportHeader(CreateWordUtil createWordUtil, MetricStatReport metricStatReport) {
		createWordUtil.addText("companyName", metricStatReport.getTitle());
		String reportSubTitle = (metricStatReport.getSubtitle() == null || metricStatReport.getSubtitle().isEmpty())
				? metricStatReportService.queryReportSubTitle(metricStatReport)
				: metricStatReport.getSubtitle();
		createWordUtil.addText("reportName", reportSubTitle);
		createWordUtil.addText("reportTime", getCurrentDateRange(metricStatReport));
		createWordUtil.addText("departName", getDeparatName(metricStatReport.getReportDepart()));
		createWordUtil.addText("createTime", getCurrentDate(new Date()));
		createWordUtil.addText("pageheader", "");
	}

	private String getCurrentDateRange(MetricStatReport metricStatReport) {
		return getCurrentDate(metricStatReport.getStDate()) + "-" + getCurrentDate(metricStatReport.getEndDate());
	}

	private void populateOverallStatistics(CreateWordUtil createWordUtil, Map<String, Object> overallStaData,
										   String durationName, MetricStatSet metricStatSet0) {
		createWordUtil.addObject("num", overallStaData.get("num"));
		createWordUtil.addObject("percent", overallStaData.get("percent"));
		createWordUtil.addText("overallDesOther", metricStatReportService.getOverallDesOther(overallStaData));
		createWordUtil.addText("statResult", getStatResult(metricStatSet0, overallStaData.get("percent")));
		createWordUtil.addText("durationName",durationName);
	}

	private List<Map<String, Object>> populateMetricDetails(List<String> nameList,List<String> codeList,List<Map<String, Object>> statData,int statMethod) {
		List<Map<String, Object>> mtrcStatList = new ArrayList<>();
		Map<Integer, List<Map<String, Object>>> detailData = metricStatReportService.list2DetailData(codeList,statData,statMethod );
		int tInd = 0;
		for (int i = 0; i < codeList.size(); i++) {
			Integer dcode = Integer.valueOf(codeList.get(i));
			List<Map<String, Object>> valData = detailData.get(dcode);
			if (valData == null || valData.isEmpty()) continue;

			Map<String, Object> tmpMap = new HashMap<>();
			String strTitle = "(" + arabic2Chinese(tInd++) + ")" + nameList.get(i);
			tmpMap.put("title", strTitle);
			tmpMap.put("desc", metricStatReportService.getDetailDes(valData));
			tmpMap.putAll(categorizeRiskLevels(valData));

			mtrcStatList.add(tmpMap);
		}
		return mtrcStatList;
	}

	private Map<String, List<String[]>> categorizeRiskLevels(List<Map<String, Object>> valData) {
		Map<String, List<String[]>> riskLevelMap = new HashMap<>();
		riskLevelMap.put("data0", new ArrayList<>());
		riskLevelMap.put("data1", new ArrayList<>());
		riskLevelMap.put("data2", new ArrayList<>());
		riskLevelMap.put("data3", new ArrayList<>());

		for (Map<String, Object> data : valData) {
			int riskLevel = data.get("riskLevel")==null?0:Integer.parseInt(data.get("riskLevel").toString());
			String fillVals = data.get("fillVals")!=null?data.get("fillVals").toString():"";
			fillVals = removeTrailingZeros(fillVals);
			if(fillVals!=null && !fillVals.equals("")){
				String unit = data.get("unit")!=null?data.get("unit").toString():"";
				fillVals += unit;
			}

			String[] tmpAry = { data.get("mtrcNo").toString(),
					data.get("mtrcName").toString(),
					getActionByRiskLevel(riskLevel, data), fillVals};
			riskLevelMap.get("data" + riskLevel).add(tmpAry);
		}
		return riskLevelMap;
	}

	private String getActionByRiskLevel(int riskLevel, Map<String, Object> data) {
		switch (riskLevel) {
			case 0: return "按时填写数据";
			case 1: return "持续监测，确保风险指标处于绿色区间";
			case 2: return data.get("geWarnAct") != null ? data.get("geWarnAct").toString() : "";
			case 3: return data.get("geTolAct") != null ? data.get("geTolAct").toString() : "";
			default: return "";
		}
	}

	private void addSuggestions(CreateWordUtil createWordUtil, Map<String, Object> overallStaData) {
		Integer lowNum = overallStaData.get("low")!=null?Integer.valueOf(overallStaData.get("low").toString()):0;
		Integer middleNum = overallStaData.get("middle")!=null?Integer.valueOf(overallStaData.get("middle").toString()):0;
		Integer hightNum = overallStaData.get("high")!=null?Integer.valueOf(overallStaData.get("high").toString()):0;
		createWordUtil.addObject("suggestLow",  lowNum> 0);
		createWordUtil.addObject("suggestMiddle", middleNum> 0);
		createWordUtil.addObject("suggestHight", hightNum> 0);
	}

	private void saveReport(Integer total, MetricStatReport metricStatReport, String newFileName, Map<String, Object> overallStaData) {
		// 获取 num 映射并确保类型安全
		Map<String, Object> staNum = (Map<String, Object>) overallStaData.get("num");

		metricStatReport.setRiskHighNum(getIntegerFromMap(staNum, "hight"));
		metricStatReport.setRiskLowNum(getIntegerFromMap(staNum, "low"));
		metricStatReport.setRiskMediumNum(getIntegerFromMap(staNum, "middle"));
		metricStatReport.setRiskOtherNum(getIntegerFromMap(staNum, "other"));

		metricStatReport.setStatTargetNum(total);
		metricStatReport.setCreateTime(new Date());

		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		metricStatReport.setCreateUser(sysUser.getUsername());
		metricStatReport.setFilepath(newFileName);

		metricStatReportService.save(metricStatReport);
	}


	private Integer getIntegerFromMap(Map<String, Object> map, String key) {
		Object value = map.get(key);
		if (value instanceof Integer) {
			return (Integer) value;
		} else if (value instanceof String) {
			return Integer.valueOf((String) value);
		}
		return 0;
	}

	private List<String> getCodeList(List<Map<String, Object>> statData) {
		List<String> codeList = new ArrayList<>();
		for (Map<String, Object> data : statData) {
			codeList.add((String) data.get("code"));  // 假设 "mtrcNo" 是指标代码
		}
		return codeList;
	}

	private List<String> getNameList(List<Map<String, Object>> statData) {
		List<String> nameList = new ArrayList<>();
		for (Map<String, Object> data : statData) {
			nameList.add((String) data.get("name"));  // 假设 "mtrcName" 是指标名称
		}
		return nameList;
	}

	private String removeTrailingZeros(String val) {
		if(val==null || val.equals("")){
			return "";
		}
		try {
			java.math.BigDecimal bd = new java.math.BigDecimal(val);
			bd = bd.stripTrailingZeros();
			String result = bd.toPlainString();
			return result;
		} catch (Exception e) {
			return val;
		}
	}
}


