package com.yeejoin.equipmanage.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.core.util.StrUtil;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.equipmanage.common.dto.AnalysisReportLogDto;
import com.yeejoin.equipmanage.common.entity.MyByteArrayMultipartFile;
import com.yeejoin.equipmanage.common.enums.WordTemplateTypeEum;
import com.yeejoin.equipmanage.common.exception.BaseException;
import com.yeejoin.equipmanage.common.exception.CommonException;
import com.yeejoin.equipmanage.common.utils.WordTemplateUtils;
import com.yeejoin.equipmanage.mapper.AnalysisReportLogMapper;
import com.yeejoin.equipmanage.service.IFirePatrolReportService;
import lombok.extern.slf4j.Slf4j;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RectangleInsets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.*;

@Slf4j
@Service
public class FilePatrolReportServiceImpl implements IFirePatrolReportService {

	@Autowired
	AnalysisReportLogMapper analysisReportLogMapper;

	@Override
	public void download(HttpServletRequest request, HttpServletResponse response, String code, Date startDate,
			Date endDate) {
		WordTemplateUtils instance = WordTemplateUtils.getInstance();
		Map<String, Object> map = getWordMap(code, startDate, endDate);
		try {
			instance.exportMillCertificateWord(request, response, map, (String) map.get("document_name"),
					WordTemplateTypeEum.firePatrolReport.getTemplateFile());
		} catch (IOException e) {
			throw new CommonException(0, "下载装备巡查报表失败");
		}
	}
	
	private Map<String, Object> getWordMap(String code, Date startDate,
			Date endDate)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		// 查询换流站
		Map<String, Object> station = analysisReportLogMapper.getStation(code);
		if(station==null||station.isEmpty()) 
		{
			throw new BaseException("换流站编码不存在");
		}
		AnalysisReportLogDto analysisReportLog = new AnalysisReportLogDto();
		analysisReportLog.setStationCode(code);
		analysisReportLog.setStartDate(startDate);
		analysisReportLog.setEndDate(endDate);
		Map<String, Object> report = analysisReportLogMapper.getReport(analysisReportLog);
		// 文档编号
		String timeStr1 = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
		String documentNumber = "ZD-XFSBXC" + timeStr1;
		map.put("document_number", documentNumber);
		// 设置文档文件名
		map.put("document_name", "消防巡查报表" + timeStr1);
		// 换流站名称
		String stationName=(String) station.get("biz_org_name");
		map.put("station_name", stationName);
		// 统计时间
		SimpleDateFormat dateStat = new SimpleDateFormat("yyyy年MM月dd日");
		String statisticalTime = dateStat.format(startDate) + "-" + dateStat.format(endDate);
		if (statisticalTime.contains("年0")) {
			statisticalTime = statisticalTime.replaceAll("年0", "年");
		}
		map.put("statistical_time", statisticalTime);
		// 生成日期
		String timeStr2 = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
		if (timeStr2.contains("年0")) {
			timeStr2 = timeStr2.replaceAll("年0", "年");
		}
		 NumberFormat nf = NumberFormat.getNumberInstance();
		 nf.setMaximumFractionDigits(0);
		SimpleDateFormat dateFm = new SimpleDateFormat("EEEE", Locale.SIMPLIFIED_CHINESE);
		String currSun = dateFm.format(new Date());
		map.put("create_date", timeStr2 + currSun);
		map.put("create_date2", timeStr2);
		// 统计时间2
		map.put("statistical_time2", statisticalTime.replaceAll("-", "至"));
		// 合格数
		int qualified = 0;
		// 未合格数
		int no_qualified = 0;
		// 巡查任务数
		int task_count = ((BigDecimal) report.get("task_count")).intValue();
		map.put("task_count", task_count);
		// 完成任务数
		int complete_task_count = ((BigDecimal) report.get("complete_task_count")).intValue();
		map.put("complete_task_count", complete_task_count);
		int uncomplete_task_count = task_count - complete_task_count;
		// 未完成任务数
		map.put("uncomplete_task_count", uncomplete_task_count);
		double complete_task_percent;
		if (0 == task_count) {
			complete_task_percent = 0.0;
			log.error("-----------------------------当天巡检计划总数是 0，请检查同步服务！-----------------------------");
		} else {
			complete_task_percent = (complete_task_count/task_count)*100;
		}
		// 任务完成率
		map.put("complete_task_percent", nf.format(complete_task_percent)+"%");
		// 任务合格
		map.put("task_qualified", uncomplete_task_count!=0?"不合格":"合格");
		if(uncomplete_task_count!=0) 
		{
			no_qualified++;
		}else 
		{
			qualified++;
		}
		// 任务完成率合格
		map.put("task_percent_qualified", complete_task_percent!=100?"不合格":"合格");
		if(complete_task_percent!=100 ) 
		{
			no_qualified++;
		}else 
		{
			qualified++;
		}
		// 巡查人员数
		int person_count = ((BigDecimal) report.get("person_count")).intValue();
		map.put("person_count", person_count);
		int certified_person_count = ((BigDecimal) report.get("certified_person_count")).intValue();
		// 持证人员数
		map.put("certified_person_count", certified_person_count);

		double certified_percent;
		if (0 == person_count) {
			certified_percent = 0.0;
			log.error("-----------------------------人员总数是 0，请检查同步服务！-----------------------------");
		} else {
			certified_percent =  (certified_person_count/person_count)*100;
		}
		// 持证率
		map.put("certified_percent", nf.format(certified_percent)+"%");
		// 人员合格
		map.put("person_qualified", certified_percent!=100?"不合格":"合格");
		if(certified_percent!=100 ) 
		{
			no_qualified++;
		}else 
		{
			qualified++;
		}
		// 应巡查设备总数
		int equipment_count = ((BigDecimal) report.get("equipment_count")).intValue();
		map.put("equipment_count", equipment_count);
		int checked_equipment_count =  ((BigDecimal) report.get("checked_equipment_count")).intValue();
		// 实际巡查设备总数
		map.put("checked_equipment_count", checked_equipment_count);
		// 实际巡查设备总数-合格
		map.put("checked_equipment_qualified", checked_equipment_count!=equipment_count?"不合格":"合格");
		if(checked_equipment_count!=equipment_count ) 
		{
			no_qualified++;
		}else 
		{
			qualified++;
		}
		// 漏查设备总数
		int unchecked_equipment_count = ((BigDecimal) report.get("unchecked_equipment_count")).intValue();
		map.put("unchecked_equipment_count", unchecked_equipment_count);
		// 漏查设备总数-合格
		map.put("unchecked_equipment_qualified", unchecked_equipment_count>0?"不合格":"合格");
		if(unchecked_equipment_count>0) 
		{
			no_qualified++;
		}else 
		{
			qualified++;
		}
		// 发现问题总数
		int problem_count = ((BigDecimal) report.get("problem_count")).intValue();
		map.put("problem_count", problem_count);
		// 修复问题总数
		int fixed_problem_count = ((BigDecimal) report.get("fixed_problem_count")).intValue();
		map.put("fixed_problem_count", fixed_problem_count);
		// 未修复问题总数
		int unfixed_problem_count = problem_count-fixed_problem_count;
		map.put("unfixed_problem_count", unfixed_problem_count);
		// 巡查点位数
		int checked_point_count = ((BigDecimal) report.get("checked_point_count")).intValue();
		map.put("checked_point_count", checked_point_count);
		// 合格饼图
		DefaultPieDataset pds = new DefaultPieDataset();
		pds.setValue("合格", qualified);
		pds.setValue("不合格", no_qualified);
		String qualified_pie_chart = getChartString(pds, "合格情况占比");
		map.put("qualified_pie_chart", qualified_pie_chart);
		// 设备巡查饼图
		DefaultPieDataset pds2 = new DefaultPieDataset();
		pds2.setValue("已查询设备", checked_equipment_count);
		pds2.setValue("漏查设备", unchecked_equipment_count);
		String equip_pie_chart = getChartString(pds2, "设备巡查占比");
		map.put("equip_pie_chart", equip_pie_chart);
		// 业务主题
		map.put("business_title", "消防巡查");
		// 缺陷清单
		List<Map<String, Object>> defect_list = analysisReportLogMapper.getDefect(analysisReportLog);
		// 缺陷总数
		map.put("defect_count", defect_list.size());
		defect_list.forEach(i->{
			i.put("defect_location", i.get("danger_position"));
			i.put("defect_description",  i.get("problem_description"));
			i.put("rectified_progress",  i.get("danger_state"));
			i.put("remark", i.get("remark"));
		});
//		Map<String, Object> defectMap = new HashMap<>();
//		defectMap.put("defect_location", "主控楼一层");
//		defectMap.put("defect_description", "仅有一条疏散通道，存在重大火灾隐患，不满足规范要求。");
//		defectMap.put("rectified_progress", "待评审");
//		defectMap.put("remark", "无法整改");
//		defect_list.add(defectMap);
//		Map<String, Object> defectMap2 = new HashMap<>();
//		defectMap2.put("defect_location", "主控楼一层");
//		defectMap2.put("defect_description", "防火卷帘门故障；11个水泵接合器存在问题；");
//		defectMap2.put("rectified_progress", "待治理");
//		defectMap2.put("remark", "防火卷帘已完成维修，水泵接合器未整改");
//		defect_list.add(defectMap2);
//		Map<String, Object> defectMap3 = new HashMap<>();
//		defectMap3.put("defect_location", "主控楼一层库房区域");
//		defectMap3.put("defect_description", "将办公用房作为库房使用，使用性质与原设计不符，耐火等级和相应消防设施不满足规范要求。");
//		defectMap3.put("rectified_progress", "治理完毕");
//		defectMap3.put("remark", "");
//		defect_list.add(defectMap3);
		map.put("defect_list", defect_list);
		return map;
	}

	/**
	 * 生成主题
	 *
	 * @param fontName 字体名称（默认为宋体）
	 * @return
	 */
	public static StandardChartTheme createChartTheme(String fontName) {
		StandardChartTheme theme = new StandardChartTheme("unicode") {
			public void apply(JFreeChart chart) {
				chart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING,
						RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
				super.apply(chart);
			}
		};
		fontName = StrUtil.isBlank(fontName) ? "宋体" : fontName;
		theme.setExtraLargeFont(new Font(fontName, Font.PLAIN, 20));
		theme.setLargeFont(new Font(fontName, Font.PLAIN, 14));
		theme.setRegularFont(new Font(fontName, Font.PLAIN, 12));
		theme.setSmallFont(new Font(fontName, Font.PLAIN, 10));
		return theme;

	}

	/**
	 * 获取饼图base64字符串
	 * 
	 * @param pds
	 * @return
	 */
	private String getChartString(DefaultPieDataset pds, String title) {
		// 设置主题 要不会乱码
		ChartFactory.setChartTheme(createChartTheme("微软雅黑"));
		JFreeChart chart = ChartFactory.createPieChart(title, pds, true, false, true);
		// 设置图例
		LegendTitle legend = chart.getLegend();
		legend.setPosition(RectangleEdge.BOTTOM);
		// 设置图例边框
		legend.setBorder(0, 0, 0, 0);
		legend.setItemFont(new Font("微软雅黑", Font.PLAIN, 16));
		// 设置最外层边框
		chart.setBorderVisible(false);
		RectangleInsets padding = new RectangleInsets(40, 40, 40, 40);
		chart.setPadding(padding);
		// 如果不使用Font,中文将显示不出来
		// 设置图片标题的字体
		chart.getTitle().setFont(new Font("微软雅黑", Font.BOLD, 24));
		// 得到图块,准备设置标签的字体
		PiePlot plot = (PiePlot) chart.getPlot();
		// 设置饼图阴影
		plot.setShadowPaint(Color.WHITE);
		plot.setAutoPopulateSectionOutlinePaint(true);
		// 设置饼图边框
		plot.setOutlineVisible(false);
		// 设置饼图一定是正圆
		plot.setCircular(true);
		// 设置起始角度
		plot.setStartAngle(90);
		// 设置饼图颜色
		plot.setSectionPaint(pds.getKey(0), Color.RED);
		plot.setSectionPaint(pds.getKey(1), Color.BLUE);
		// 设置饼图边框颜色

		// 设置plot的前景色透明度
		plot.setForegroundAlpha(0.7f);
		// 设置plot的背景色透明度
		plot.setBackgroundAlpha(0.0f);
		// 设置标签字体
		plot.setLabelFont(new Font("微软雅黑", Font.PLAIN, 16));
		// 设置分类标签字体颜色
		// plot.setLabelPaint(Color.RED);
		//plot.setLabelLinkPaint(Color.RED);
		// 设置分类标签背景颜色
		plot.setLabelBackgroundPaint(Color.WHITE);
		// 设置分类标签边框颜色
		plot.setLabelOutlinePaint(Color.WHITE);
		plot.setLabelShadowPaint(Color.WHITE);
		// 设置标签生成器(默认{0})
		// {0}:key {1}:value {2}:百分比 {3}:sum
		StandardPieSectionLabelGenerator labelGenerator = new StandardPieSectionLabelGenerator("{0}\n{2}");
		plot.setLabelGenerator(labelGenerator);
		
		BufferedImage image = chart.createBufferedImage(600,350);
		byte[] bytes = null;
		try {
			bytes = ChartUtilities.encodeAsPNG(image);
		} catch (IOException e1) {
			throw new CommonException(0, "生成饼图失败");
		}
		String base64 = Base64.getEncoder().encodeToString(bytes);
		return base64;
	}


	@Override
	public IPage<AnalysisReportLogDto> allPage(Page<AnalysisReportLogDto> page, Integer reportType, Date startDate,
			Date endDate, String stationCode) {
		AnalysisReportLogDto analysisReportLog = new AnalysisReportLogDto();
		analysisReportLog.setStartDate(startDate);
		analysisReportLog.setEndDate(endDate);
		analysisReportLog.setReportType(reportType);
		analysisReportLog.setStationCode(stationCode);
		Long rootParentId = Long.valueOf(String.valueOf(analysisReportLogMapper.getRootOrgUsr().get("sequence_nbr")));
		return analysisReportLogMapper.allPage(page, analysisReportLog, rootParentId);
	}

	@Override
	public String preview(String code, Date startDate, Date endDate) {
		WordTemplateUtils instance = WordTemplateUtils.getInstance();
		Map<String, Object> map = getWordMap(code, startDate, endDate);
		String urlString="";
		try {
			//instance.pdfCreate(map, (String) map.get("document_number"), WordTemplateTypeEum.firePatrolReport.getTemplateFile());
			File filepdf = instance.getWordFileItem(map,(String) map.get("document_number"), WordTemplateTypeEum.firePatrolReport.getTemplateFile());
			//MultipartFile multipartFile = new CommonsMultipartFile(item);
			filepdf.getAbsolutePath();
//            File file = new File("F:\\application-dev.yml");
//           FileInputStream input = new FileInputStream(filepdf);
            MultipartFile multipartFile = new MyByteArrayMultipartFile("file","file.pdf","application/pdf",file2byte(filepdf));
			FeignClientResult<java.util.Map<String, String>> result = Systemctl.fileStorageClient.updateCommonFile(multipartFile);
	    		if (result != null) {
	    			Iterator<String> it = result.getResult().keySet().iterator();
	    			while (it.hasNext()) {
	    				urlString=it.next();
	    			}
	    		}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return urlString;
	}
	
	public static byte[] file2byte(File file)
	{
		try {
			FileInputStream in =new FileInputStream(file);
			//当文件没有结束时，每次读取一个字节显示
			byte[] data=new byte[in.available()];
			in.read(data);
			in.close();
			return data;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

//	@Override
//	public IPage<AnalysisReportLogDto> listPage(Page<AnalysisReportLogDto> page, Integer reportType, Date startDate,
//			Date endDate,String stationCode) {
//		AnalysisReportLogDto analysisReportLog = new AnalysisReportLogDto();
//		analysisReportLog.setReportType(reportType);
//		analysisReportLog.setStationCode(stationCode);
//		analysisReportLog.setEndDate(startDate);
//		analysisReportLog.setStartDate(endDate);
//		return analysisReportLogMapper.allPage(page, analysisReportLog);
//	}
}
