package com.yonyou.hrcloud.pm.base.model;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.util.WebUtils;

import com.yonyou.hrcloud.adder.context.AppContext;
import com.yonyou.hrcloud.adder.context.SpringHelper;
import com.yonyou.hrcloud.adder.exception.AdderBusinessException;
import com.yonyou.hrcloud.adder.exception.AdderRuntimeException;
import com.yonyou.hrcloud.file.helper.FileHelper;
import com.yonyou.hrcloud.pm.helper.LoggerDecorator;

/**
 * Created by nijb on 2019/8/26.
 */
public class ImportExcel {

	private String[] heads_name = null;// 表头内容

	private String[] heads_code = null;// 表头code
		
	private Workbook workbook; // workbook实体

	private Sheet default_sheet; // 要操作Sheet实体

	private List<Integer> effective_row_num; // 有数据的行

	protected static final Logger logger = new LoggerDecorator(ImportExcel.class);

	/**
	 * 获取上传的表格实体
	 * 
	 * @param request
	 * @param response
	 * @param sheetName
	 * @return
	 */
	public ImportExcel(HttpServletRequest request, HttpServletResponse response, 
			String[][] headsinfo, String sheetName) {
		this.heads_name = new String[headsinfo.length];
		this.heads_code = new String[headsinfo.length];
		for(int i = 0; i< headsinfo.length; i++){
			heads_name[i] = headsinfo[i][0];
			heads_code[i] = headsinfo[i][1];
		}
		this.effective_row_num = new ArrayList<Integer>();
		// 获取 workbook
		MultipartFile[] f = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class)
								.getFileMap().values().toArray(new MultipartFile[0]);
		MultipartFile file = (f == null || f.length == 0 ? null : f[0]);
		if (file == null || StringUtils.isEmpty(file.getOriginalFilename()) 
				|| (!file.getOriginalFilename().endsWith("xls") && !file.getOriginalFilename().endsWith("xlsx")))
			throw new AdderBusinessException("请选择正确的文件类型进行上传。", "pm.i18n_core.ps.064");
		try {
			workbook = (file.getOriginalFilename().endsWith("xlsx") ? new XSSFWorkbook(file.getInputStream())
					: new HSSFWorkbook(file.getInputStream()));
		} catch (IOException e) {
			throw new AdderBusinessException("请选择上传文件！", "pm.i18n_core.ps.061");
		}
		if (StringUtils.isEmpty(sheetName) || (default_sheet = workbook.getSheet(sheetName)) == null)
			default_sheet = workbook.getSheetAt(0);
		if (default_sheet == null || default_sheet.getRow(0) == null)
			throw new AdderBusinessException("请使用正确的导入模板进行导入。", "pm.i18n_core.ps.062");
		for (int i = 0; i < heads_name.length; i++){
			if (default_sheet.getRow(0).getCell(i) == null || !heads_name[i].equals(default_sheet.getRow(0).getCell(i).toString()))
				throw new AdderBusinessException("请使用正确的导入模板进行导入。", "pm.i18n_core.ps.062");
		}
	}

	/**
	 * @return List<Map<String,Object></>> 返回类型
	 * @Title: importExcel
	 */
	public List<Map<String, Object>> readExcel() {
		List<Map<String, Object>> rightData = new ArrayList<>();
		// 正文内容应该从第二行开始,第一行为表头的标题
		for (int i_row = 1; i_row <= default_sheet.getLastRowNum(); i_row++) {
			if (default_sheet.getRow(i_row) == null)
				continue;
			Map<String, Object> indidata = new HashMap<String, Object>();
			for (int col = 0; col < heads_code.length; col++) {
				Cell cell = default_sheet.getRow(i_row).getCell(col);
				if (cell == null || StringUtils.isEmpty(cell.toString().trim()))
					continue;
				if(heads_code[col].endsWith("_weight")){
					if (cell.getCellStyle().getDataFormatString().indexOf("%") != -1)
						indidata.put(heads_code[col], new BigDecimal(cell.getNumericCellValue()+"")
								.multiply(new BigDecimal("100")).doubleValue()+"" );
					else 
						indidata.put(heads_code[col], cell.toString().trim().replace("%", ""));	
				} else {
					cell.setCellType(CellType.STRING); // 需要先设置单元格类型，才能读取字符串，直接读数字会含小数点
					indidata.put(heads_code[col], cell.getStringCellValue().trim());
				}
			}
			if (indidata.size() > 0) {
				rightData.add(indidata);
				effective_row_num.add(i_row);
			}
		}
		if(rightData.size() <= 0){
			throw new AdderBusinessException("导入数据不可为空。", "pm.i18n_core.ps.080");
		}
		return rightData;
	}

	/**
	 * 将错误信息写入excel中
	 *
	 * @param errormap,双重map<row,<col,str>>
	 * @return
	 */
	public String writeErrormsgToExcel(Map<Integer, Map<Integer, String>> errormap) {
		// 错误提示背景色
		CellStyle error_style = workbook.createCellStyle();
		error_style.setFillForegroundColor(IndexedColors.RED.getIndex());
		error_style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		// 警告背景色
		CellStyle warn_style = workbook.createCellStyle();
		warn_style.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
		warn_style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		default_sheet.getRow(0).createCell(heads_code.length, CellType.STRING).setCellValue("错误日志");
		// 正文内容应该从第二行开始,第一行为表头的标题
		Iterator<Integer> row_iter = errormap.keySet().iterator();
		while (row_iter.hasNext()) {
			Integer rowindex = row_iter.next();
			Row row = default_sheet.getRow(effective_row_num.get(rowindex));
			if (row == null)
				continue;
			Iterator<Integer> col_iter = errormap.get(rowindex).keySet().iterator();
			StringBuffer errorInfo = new StringBuffer("");
			while (col_iter.hasNext()) {
				Integer colindex = col_iter.next();
				Cell cell = (row.getCell(colindex - 1) == null 
						? row.createCell(colindex - 1, CellType.STRING): row.getCell(colindex - 1));
				errorInfo.append(((char) (64 + colindex)) + "" + (effective_row_num.get(rowindex) + 1))
								.append(errormap.get(rowindex).get(colindex));
				cell.setCellStyle(error_style);
			}
			Cell newCell = row.createCell(heads_code.length, CellType.STRING);
			newCell.setCellValue(errorInfo.toString());
			default_sheet.setColumnWidth(heads_code.length, 25 * 256);
			newCell.setCellStyle(warn_style);
		}
		return uploadErrorExcel();
	}
	
	/**
	 * 上传含有错误日志的excel到云盘
	 * 
	 * @return
	 */
	private String uploadErrorExcel() {
		try {
			String tempFileDir = SpringHelper.getRealPath() + "attachment_temp_folder" + File.separator
					+ AppContext.getContext().getScope() + File.separator + AppContext.getContext().getUserId();
//			String tempFileDir = "D:\\\\"+"attachment_temp_folder" + File.separator
//					+ AppContext.getContext().getScope() + File.separator + AppContext.getContext().getUserId();
			// 临时目录用来存放所有分片文件
			File parentFileDir = new File(tempFileDir);
			if (!parentFileDir.exists())
				parentFileDir.mkdirs();
			logger.debug("####pm-uploadChunk:tempFileDir-{}", tempFileDir);
			// 目标文件
			String fileName = "SheetErrortEmplate" + (workbook instanceof XSSFWorkbook ? ".xlsx" : ".xls");
			File destTempFile = new File(tempFileDir, fileName);
			OutputStream outputStream = new FileOutputStream(destTempFile);
			workbook.write(outputStream);
			outputStream.close();
			// 上传阿里云
			String pubKey = String.format("%s/%s/%s%s", AppContext.getContext().getScope(), "pm-core",
					AppContext.getContext().getUserId(), (workbook instanceof XSSFWorkbook ? ".xlsx" : ".xls"));
			logger.debug("####pm-uploadChunk:pubKey-{}", pubKey);
			//OSSHelper.uploadInPub(pubKey, new FileInputStream(destTempFile));
			// diwork是https的
			//String url = URLDecoder.decode(OSSHelper.getUrlPub(pubKey).replace("http:", "https:"), "UTF-8");
			if(FileHelper.exist(pubKey)){
				FileHelper.delete(pubKey);
			}
			FileInputStream inputStream = new FileInputStream(destTempFile);
			FileHelper.upload(pubKey, inputStream);
			inputStream.close();
			String url = FileHelper.getUrl(pubKey);
			logger.debug("####pm-uploadChunk:oss_url-{}", url);
			FileUtils.deleteDirectory(parentFileDir);// 删除临时文件夹
			return pubKey;
		} catch (Exception ex) {
			logger.error("####pm uploadChunk error:{}", ex);
			throw new AdderRuntimeException(ex.getMessage());
		}
	}
}