package com.product.module.data.service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.product.core.config.CoreConst;
import com.product.core.dao.BaseDao;
import com.product.core.entity.DataTableEntity;
import com.product.core.entity.FieldSetEntity;
import com.product.core.entity.RequestParameterEntity;
import com.product.core.exception.BaseException;
import com.product.core.service.support.AbstractBaseService;
import com.product.module.data.config.CmnCode;
import com.product.module.data.config.CmnConst;
import com.product.module.data.utli.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

/**
 * @Author cheng
 * @Description 鏁版嵁瀵煎嚭service
 * @Date 2021/6/10 15:02
 * @Version 1.0
 */
@Service
public class SystemDataExportService extends AbstractBaseService {
	@Autowired
	SystemApiToMethods systemApiToMethods;

	@Override
	public BaseDao getBaseDao() {
		return super.getBaseDao();
	}

	public void reportDataExport(FieldSetEntity fse) throws BaseException {
		//鎶ヨ〃uuid
		String uuid = fse.getUUID();
		//鏄惁褰撳墠椤�
		boolean exportCurrentPage = fse.getBoolean("exportCurrentPage");
		//褰撳墠椤靛彿
		int pageIndex = fse.getInteger(CmnConst.CPAGE);

	}

	/**
	 * 鏁版嵁鎶ヨ〃瀵煎嚭
	 *
	 * @param reqp
	 * @return 杩斿洖Base64 EXCEL.XLSX
	 * @throws BaseException
	 * @throws IOException
	 */
	public String reportDataExport(RequestParameterEntity reqp) throws BaseException {

		FieldSetEntity formData = reqp.getFormData();
		//鎬诲垪鏁�
		Integer totalColumn = formData.getInteger("totalColumn");
		//鎬昏鏁�
		Integer totalRows = formData.getInteger("totalRows");
		//澶撮儴鍖哄煙琛屾暟
		Integer headCount = formData.getInteger("headCount");
		Map<String, File> files = reqp.getFiles();
		//鍥哄畾鏂囦欢鍚�
		File portExcel = files.get("portExcel.xlsx");
		try (InputStream inputStream = new FileInputStream(portExcel); XSSFWorkbook wb = new XSSFWorkbook(inputStream)) {
			XSSFSheet sheet = wb.getSheetAt(0);
			//鑾峰彇澶撮儴鏍峰紡
			XSSFCellStyle headStyle = getReportStyle(wb, IndexedColors.BLACK.getIndex(), true, (short) 15, new java.awt.Color(191, 191, 191));
			//鑾峰彇鏁版嵁鍖烘牱寮�
			XSSFCellStyle dataStyle = getReportStyle(wb, IndexedColors.BLACK.getIndex(), false, (short) 13, new java.awt.Color(255, 255, 255));
			//鎵€鏈夊悓鍒楁渶瀹�
			Map<Integer, Integer> m = new HashMap<>();
			for (int i = 0; i < totalRows; i++) {
				XSSFRow row = sheet.getRow(i);
				XSSFCellStyle style = null;
				if (i < headCount) {
					//澶撮儴鍖哄煙鏍峰紡
					style = headStyle;
				} else {
					//鏁版嵁鍖烘牱寮�
					style = dataStyle;
				}
				//閬嶅巻姣忎竴涓崟鍏冩牸
				for (int j = 0; j < totalColumn; j++) {
					//鑾峰彇鍗曞厓鏍煎璞�
					XSSFCell cell = row.getCell(j);
					if (cell == null) {
						//濉厖绌虹殑鍗曞厓鏍�
						cell = row.createCell(j, CellType.STRING);
					}
					//璁剧疆鍗曞厓鏍兼牱寮�
					cell.setCellStyle(style);
					//鑾峰彇鍗曞厓鏍煎€�
					String val = cell.getStringCellValue();
					if (val != null) {
						//鏍规嵁瀛楄妭璁$畻澶ц嚧瀹藉害
						int i2 = val.getBytes().length * 256;
						//瀹藉害涓嶈兘瓒呰繃 256*256
						if (i2 > 256 * 256) {
							i2 = 256 * 255;
						}
						if (m.get(j) == null) {
							m.put(j, i2);
						} else {
							//褰撳墠琛岀殑鍒楁槸鍚︽瘮鍏朵粬琛岀殑鍒楀
							Integer width = m.get(j);
							if (width < i2) {
								m.put(j, i2);
							}
						}
					}

				}
			}
			//璁剧疆姣忓垪鐨勫搴�
			for (Map.Entry<Integer, Integer> v : m.entrySet()) {
				sheet.setColumnWidth(v.getKey(), v.getValue());
			}
			//灏唚orkbook杞崲涓哄瓧鑺傛祦
			ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
			//灏唀xcel杈撳嚭鍒板瓧鑺傛祦
			wb.write(byteArrayOutputStream);
			//灏嗗瓧鑺傛祦杞负瀛楄妭
			byte[] bytes = byteArrayOutputStream.toByteArray();
			//灏嗗瓧鑺傝浆鎹负Base64
			String encode = Base64.getEncoder().encodeToString(bytes);
			//鍒犻櫎浼犲叆鐨勬枃浠�
			if (portExcel != null && portExcel.exists()) {
				portExcel.delete();
			}
			//杩斿洖Base64瀛楃涓� 鎷兼帴XLSX鏂囦欢鏍煎紡鍓嶇紑
			return "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64," + encode;
		} catch (Exception e) {
			throw new BaseException(CmnCode.EXPORT_REPORT_DATA_FIAL.getValue(), CmnCode.EXPORT_REPORT_DATA_FIAL.getValue() + e.getMessage());
		}
	}

	/**
	 * 鍗曞厓鏍兼牱寮�
	 *
	 * @param workbook
	 * @param color    瀛椾綋棰滆壊
	 * @param bold     鏄惁鍔犵矖
	 * @param fontSize 瀛椾綋澶у皬
	 * @param bgc      鑳屾櫙鑹�
	 * @return
	 */
	public XSSFCellStyle getReportStyle(XSSFWorkbook workbook, short color, boolean bold, short fontSize, java.awt.Color bgc) {
		XSSFCellStyle cellStyle = workbook.createCellStyle();
		//宸﹀彸灞呬腑
		cellStyle.setAlignment(HorizontalAlignment.CENTER);
		//涓婁笅灞呬腑
		cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
		// 涓嬭竟妗�
		cellStyle.setBorderBottom(BorderStyle.THIN);
		// 宸﹁竟妗�
		cellStyle.setBorderLeft(BorderStyle.THIN);
		// 涓婅竟妗�
		cellStyle.setBorderTop(BorderStyle.THIN);
		// 鍙宠竟妗�
		cellStyle.setBorderRight(BorderStyle.THIN);
		//璁剧疆鑳屾櫙鑹�
//        cellStyle.setFillForegroundColor(new XSSFColor());
		//濉厖妯″紡
		cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		XSSFFont font = workbook.createFont();
		//瀛椾綋棰滆壊
		font.setColor(color);
		//鍔犵矖
		font.setBold(bold);
		//瀛椾綋澶у皬
		font.setFontHeightInPoints(fontSize);
		//瀛椾綋鏍峰紡
		font.setFontName("寰蒋闆呴粦");
		//鑷姩鎹㈣
		cellStyle.setWrapText(true);
		cellStyle.setFont(font);
		return cellStyle;
	}


	/**
	 * 閫氱敤鍒楄〃瀵煎嚭
	 *
	 * @param fse
	 * @throws BaseException
	 */
	public void generalListDataExport(FieldSetEntity fse) throws BaseException {
		//瀵煎嚭鏂囦欢鍚嶇О
		String file_name = fse.getString(CmnConst.FILE_NAME);
		//鏁版嵁鎺ュ彛
		String upload_api_url = fse.getString(CmnConst.UPLOAD_API_URL);
		//鏁版嵁鎺ュ彛鎵€闇€鍙傛暟
		FieldSetEntity export_param = fse.getSubDataTable(CmnConst.EXPORT_PARAM).getFieldSetEntity(0);
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		RequestParameterEntity requestParameterEntity = (RequestParameterEntity) request.getAttribute(CoreConst.API_POST_REQUEST_DATA);
		FieldSetEntity fs = new FieldSetEntity();
		fs.setTableName(fse.getString(CmnConst.TABLE_NAME));
		//寮€濮嬮〉
		int start_cpage = export_param.getInteger(CmnConst.START_CPAGE);
		//缁撴潫椤�
		int end_cpage = export_param.getInteger(CmnConst.END_CPAGE);
		int pagesize = export_param.getInteger(CmnConst.PAGESIZE);
		export_param.setValue(CmnConst.CPAGE, ((start_cpage) * pagesize) / pagesize);
		export_param.setValue(CmnConst.PAGESIZE, pagesize * ((end_cpage - start_cpage) + 1));
		export_param.remove(CmnConst.START_CPAGE);
		export_param.remove(CmnConst.END_CPAGE);
		Map<Object, Object> values = export_param.getValues();
		for (Map.Entry<Object, Object> v : values.entrySet()) {
			fs.setValue(v.getKey().toString(), v.getValue());
		}
		requestParameterEntity.setFormData(fs);
		String result = (String) systemApiToMethods.run(upload_api_url, 1);

		if (JSON.isValidObject(result)) {
			JSONObject resultJson = JSON.parseObject(result);
			if (200 == resultJson.getInteger("code")) {
				//鑾峰彇鏁版嵁鎴愬姛
				Object data = resultJson.get("data");
				if (data instanceof JSONObject) {
				} else if (data instanceof JSONArray) {
					DataTableEntity export_field = export_param.getSubDataTable("export_field");
					try {
						writeExcel((JSONArray) data, export_field, file_name);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			} else {
				throw new BaseException(resultJson.getString("code"), resultJson.getString("msg"));
			}
		} else {
			System.out.println("鏈煡鐨勬暟鎹被鍨�");
		}
	}

	/**
	 * 杈撳嚭excel
	 *
	 * @param data
	 * @param fieldInfo
	 * @param main_title
	 * @throws IOException
	 */
	public void writeExcel(JSONArray data, DataTableEntity fieldInfo, String main_title) throws IOException {
		//鏍囬
		List<List<String>> headTitles = Lists.newArrayList();
		List<String> fields = Lists.newArrayList();
		//瀵煎嚭鐨勬暟鎹泦
		List<String> titles = Lists.newArrayList();
		List<String> titleTemplate = Lists.newArrayList();
		titleTemplate.add(main_title);
		for (int i = 0; i < fieldInfo.getRows(); i++) {
			titles.add(fieldInfo.getString(i, CmnConst.FIELD_DESC));
			fields.add(fieldInfo.getString(i, CmnConst.FIELD_NAME));
		}
		List<List<Object>> lists = contentData(data, fields);
		titles.forEach(title -> {
			List<String> secondTitle = Lists.newArrayList(titleTemplate);
			secondTitle.add(title);
			headTitles.add(secondTitle);
		});
		HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
		response.setContentType("multipart/form-data");
		response.setCharacterEncoding("utf-8");
		// 杩欓噷URLEncoder.encode鍙互闃叉涓枃涔辩爜 褰撶劧鍜宔asyexcel娌℃湁鍏崇郴
		writeExcel(headTitles, lists, main_title, response);
	}

	/**
	 * 杈撳嚭excel
	 *
	 * @param excelHeaders excel琛ㄥご
	 * @param dataRows     鏁版嵁琛�
	 * @param sheetName    sheet鍚嶇О
	 * @throws IOException
	 */
	public void writeExcel(List<List<String>> excelHeaders, List dataRows, String sheetName, HttpServletResponse response) throws IOException {

		response.setContentType("multipart/form-data");
		response.setCharacterEncoding("utf-8");
		//鍏佽璁块棶header涓殑鑷畾涔夊弬鏁�
		response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
		//璁剧疆鏂囦欢鍚�
		response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(sheetName + System.currentTimeMillis() + ".xlsx", "UTF-8"));
		// 杩欓噷URLEncoder.encode鍙互闃叉涓枃涔辩爜 褰撶劧鍜宔asyexcel娌℃湁鍏崇郴
		// 杩欓噷闇€瑕佽缃笉鍏抽棴娴�
		try (ServletOutputStream outputStream = response.getOutputStream();) {
			EasyExcel.write(outputStream).
					registerWriteHandler(new Custemhandler()).head(excelHeaders).sheet(sheetName).doWrite(dataRows);
		}
	}


	/**
	 * 缁勮鏁版嵁
	 *
	 * @param dataArray
	 * @param fields
	 * @return
	 */
	private static List<List<Object>> contentData(JSONArray dataArray, List<String> fields) {
		List<List<Object>> contentList = Lists.newArrayList();
		dataArray.forEach(data -> {
			JSONObject dataJson = (JSONObject) data;
			List<Object> content = Lists.newArrayList();
			fields.forEach(field -> {
				content.add(dataJson.get(field));
			});
			contentList.add(content);
		});
		return contentList;
	}


}