package com.langtech.plm.performancemanagement.operations;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.langtech.plm.performancemanagement.util.ProgressBarThread;
import com.langtech.plm.performancemanagement.util.SqlUtil;
import com.teamcenter.rac.aif.AbstractAIFOperation;
import com.teamcenter.rac.kernel.TCComponent;
import com.teamcenter.rac.kernel.TCComponentDataset;
import com.teamcenter.rac.kernel.TCComponentTcFile;
import com.teamcenter.rac.kernel.TCException;
import com.teamcenter.rac.kernel.TCProperty;
import com.teamcenter.rac.kernel.TCSession;
import com.teamcenter.rac.util.FileUtility;
import com.teamcenter.rac.util.MessageBox;

public class TaskFolderMatchingOperation extends AbstractAIFOperation {
//	private AbstractAIFApplication app;
	private String filePath;
	private TCSession session;

	private ProgressBarThread wait;
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
	TCComponent target;
	Date processStartDate = null;
	Date processEndDate = null;

	public TaskFolderMatchingOperation(String filePath, TCComponent target, TCSession session, ProgressBarThread wait) {
		this.filePath = filePath;
		this.target = target;
		this.session = session;
		this.wait = wait;
	}

	@Override
	public void executeOperation() throws Exception {
		String[] ldSqlServer = session.getPreferenceService().getStringValues("ld_sqlserver");
		if (!getMessageInfo(ldSqlServer, "ld_sqlserver")) {
			return;
		}

		// 检查报表模板是否存在（首选项ld_billboards_uid）
		String ldBillboardsUid = session.getPreferenceService().getStringValue("ld_billboards_uid");
		if (!getMessageboxInfo(ldBillboardsUid, "ld_billboards_uid")) {
			return;
		}
		TCComponent billboard = null;
		try {
			billboard = session.stringToComponent(ldBillboardsUid);
		} catch (TCException e) {
			e.printStackTrace();
			MessageBox.post("请通知管理员检查首选项ld_billboards_uid是否配置", "", MessageBox.INFORMATION);
			return;
		}
		if (billboard == null) {
			MessageBox.post("请通知管理员检查首选项ld_billboards_uid是否配置", "", MessageBox.INFORMATION);
			return;
		}
		// 获取岗位系数 任务性质 难度系数 紧张度系数 要求完成时间公式的首选项
		String[] ldPostCoefficient = session.getPreferenceService().getStringValues("ld_postCoefficient");
		String[] ldTaskNature = session.getPreferenceService().getStringValues("ld_taskNature");// 任务性质对应的系数
		String[] ldTaskDifficulty = session.getPreferenceService().getStringValues("ld_taskDifficulty");// 难度系数
		String[] ldUrgency = session.getPreferenceService().getStringValues("ld_urgency");
		// 超时配置
		String[] ldOvertime = session.getPreferenceService().getStringValues("ld_overtime");// 严重等级:天数区间（整数）[0,0]:扣分系数;一般:(0,1]:1/5;严重:(1,2]:1/3;超严重:(2,3]:1/2;未定义:[3,1000):0.6
		// 流程信息配置成 任务包名称=流程名称:审核节点名称
		String[] ldProcessReview = session.getPreferenceService().getStringValues("ld_processReview");
		// 要求完成时间公式 多值形式 新品任务项名称=要求完成时间公式 例如铸件资料=E-30 其中 E代表流程发起时间 F代表工艺程序结束时间
		String[] ldRequestTime = session.getPreferenceService().getStringValues("ld_requestTime");
		if (!getMessageInfo(ldPostCoefficient, "ld_processReview")) {
			return;
		}
		if (!getMessageInfo(ldTaskNature, "ld_taskNature")) {
			return;
		}
		if (!getMessageInfo(ldUrgency, "ld_urgency")) {
			return;
		}
		if (!getMessageInfo(ldTaskDifficulty, "ld_taskDifficulty")) {
			return;
		}
		if (!getMessageInfo(ldProcessReview, "ld_processReview")) {
			return;
		}
		if (!getMessageInfo(ldOvertime, "ld_overtime")) {
			return;
		}
		if (!getMessageInfo(ldRequestTime, "ld_requestTime")) {
			return;
		}
		Map<String, String> postCoefficientMap = new HashMap<String, String>();// 岗位，岗位系数
		Map<String, String> taskNatureMap = new HashMap<String, String>();// 任务性质，任务系数
		Map<String, String> taskDifficultyMap = new HashMap<String, String>();// 任务难度，难度系数
		Map<String, String> urgencyMap = new HashMap<String, String>();// 紧急程度，紧急程度系数
		Map<String, String> processReviewMap = new HashMap<String, String>();// 流程名称，指派的节点名称
		Map<String, String> severityIntervalMap = new HashMap<String, String>();// 键：天数区间；值：扣分系数
		Map<String, String> requestTimeMap = new HashMap<String, String>();// 键：新品任务项名称；值：公式
		for (int i = 0; i < ldPostCoefficient.length; i++) {
			String value = ldPostCoefficient[i];
			postCoefficientMap.put(value.split("=")[0], value.split("=")[1]);
		}
		for (int i = 0; i < ldRequestTime.length; i++) {
			String value = ldRequestTime[i];
			requestTimeMap.put(value.split("=")[0], value.split("=")[1]);
		}
		for (int i = 0; i < ldTaskNature.length; i++) {
			String value = ldTaskNature[i];
			taskNatureMap.put(value.split("=")[0], value.split("=")[1]);
		}
		for (int i = 0; i < ldTaskDifficulty.length; i++) {
			String value = ldTaskDifficulty[i];
			taskDifficultyMap.put(value.split("=")[0], value.split("=")[1]);
		}
		for (int i = 0; i < ldUrgency.length; i++) {
			String value = ldUrgency[i];
			urgencyMap.put(value.split("=")[0], value.split("=")[1]);
		}
		for (int i = 0; i < ldProcessReview.length; i++) {
			String value = ldProcessReview[i];
			processReviewMap.put(value.split("=")[0], value.split("=")[1]);
		}
		for (int i = 0; i < ldOvertime.length; i++) {
			String dayInterval = ldOvertime[i].split(":")[1];
//			String severity = ldOvertime[i].split(":")[0];
			String point = ldOvertime[i].split(":")[2];
			severityIntervalMap.put(dayInterval, point);
		}
		// 下载报表命名引用和任务要求表的命名引用
		String billboardAddress = downLoadFile(billboard);
		// TODO 获取工艺结束时间
		String targetName = "";
		try {
			targetName = target.getProperty("object_name");
		} catch (TCException e) {
			e.printStackTrace();
		}
		getProcessTime(targetName);// E、 F
		if (processEndDate == null || processStartDate == null) {
			MessageBox.post("请检查是否设置或者导入相关客户成品文件夹名称和工艺程序结束时间", "", MessageBox.INFORMATION);
			return;
		}
		// 获取任务包的流程 组织
		// 先遍历底层结构
		String path = "";
		String link = "/";
		List<String> taskPathList = new ArrayList<String>();
		Map<String, TCComponent> folderMap = new HashMap<String, TCComponent>();// 键：文件夹层级结构 值：文件夹对象
		getAllFolderPath(target, path, link, taskPathList, folderMap);
		// 获取首选项Connor_JXFolder
		Map<String, List<String>> packageMap = new HashMap<String, List<String>>();
		String connorJXFolderPreference = "Connor_JXFolder";
		String[] ConnorJXFolders = session.getPreferenceService().getStringValues(connorJXFolderPreference);
		if (!getMessageInfo(ConnorJXFolders, connorJXFolderPreference)) {
			return;
		}
		for (int i = 0; i < ConnorJXFolders.length; i++) {
			String[] values = ConnorJXFolders[i].split("=");
			String[] folders = values[1].split(";");
			List<String> folderList = Arrays.asList(folders);
			packageMap.put(values[0], folderList);
		}
		// 读取报表信息
		File file = new File(billboardAddress);
		XSSFWorkbook workbook = null;
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(file);
			workbook = new XSSFWorkbook(fis);
		} catch (IOException e) {
			e.printStackTrace();
		}
		XSSFSheet sheet = workbook.getSheet("新品任务分配表");
		int rowNum = sheet.getLastRowNum();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HHmm");
		for (int i = 1; i < rowNum; i++) {
			XSSFRow row = sheet.getRow(i);
			String cellBValue = row.getCell(1).getStringCellValue().trim();// 任务包名
			List<String> folderList = packageMap.get(cellBValue);
			if (folderList != null && folderList.size() > 0) {
				String folderPath = folderList.get(0);
				System.out.println("任务包名：" + folderPath);
				TCComponent folder = folderMap.get(folderPath);
				if (folder == null) {
					continue;
				}
				// "任务性质", "难易程度", "紧急程度", "额定业务工时(小时)",
				String[] properties = new String[] { "object_desc", "ld6_WorkFold01", "ld6_WorkFold02",
						"ld6_WorkFold03", "ld6_WorkFold04", "fnd0AllWorkflows" };
				TCProperty[] tcproperties = null;
				try {
					tcproperties = folder.getTCProperties(properties);
				} catch (TCException e) {
					e.printStackTrace();
				}
				// 新品任务要求描述
				String objectDesc = tcproperties[0].getStringValue();
				String taskNature = tcproperties[1].getDisplayValue();
				String difficulty = tcproperties[2].getDisplayValue();
				String urgency = tcproperties[3].getDisplayValue();
				String ratedBusinessHours = tcproperties[4].getStringValue();
				String taskNatureCoefficient = taskNatureMap.get(taskNature);
				String taskDifficultyCoefficient = taskDifficultyMap.get(difficulty);
				String urgencyCoefficient = urgencyMap.get(urgency);
				String postCoefficient = "";// 待定
				// 获取流程信息
				String processReview = processReviewMap.get(cellBValue);
				System.out.println("processReview:" + processReview);
				if (processReview.length() == 0) {
					continue;
				}
				String processName = processReview.split(":")[0];
				String reviewName = processReview.split(":")[1];
				String assignee = "";// 被指派者fnd0Assignee，如果流程任务没有经过转发，被指派者即流程接受者；等同于责任方
				String assigner = "";// 指派者fnd0Assigner，如果流程任务没有经过转发，这个属性没有值，可以取被指派者
				String assigneeGroup = "";// 被指派者的组
				String status = "";// 流程状态
//				String startData = "";// 流程开始时间
				String endDateValue = "";// 流程结束时间
				String actualHours = "";// 实际业务工时
				String deductPoints = "";// 超时扣分
//				String remark = "";// 备注（暂时让用户导出后，自己手填）
				String assignStartDay = "";// 任务分派时间
				String requestEndDay = "";// 要求完成时间
				row.getCell(5).setCellValue(objectDesc);
				row.getCell(8).setCellValue(taskNature);
				row.getCell(9).setCellValue(difficulty);
				row.getCell(10).setCellValue(urgency);
				row.getCell(11).setCellValue(ratedBusinessHours);
				TCComponent[] workflows = tcproperties[5].getReferenceValueArray();
				for (int j = 0; j < workflows.length; j++) {
					TCComponent workflow = workflows[j];
					try {
						String[] workflowProperties = new String[] { "object_name", "fnd0ActuatedInteractiveTsks",
								"fnd0EndDate", "fnd0StartDate", "fnd0Status" };
						TCProperty[] workflowTcProperties = workflow.getTCProperties(workflowProperties);
						String workflowName = workflowTcProperties[0].getDisplayValue();
						TCComponent[] reviews = workflowTcProperties[1].getReferenceValueArray();
						if (workflowName.equals(processName)) {
							for (int k = 0; k < reviews.length; k++) {
								TCComponent review = reviews[k];
								String typeName = review.getType();
								System.out.println("流程节点类型：" + typeName);
								if (typeName.equals("签发") || typeName.equals("Signoff")) {// 任务：fnd0AliasTaskName;执行者：fnd0Performer
									// fnd0AssigneeGroupRole owning_group
									String[] reviewProperties = new String[] { "fnd0AliasTaskName", "fnd0Performer",
											"owning_group", "fnd0Assigner", "fnd0Assignee" };
									TCProperty[] reviewTcProperties = review.getTCProperties(reviewProperties);
									String aliasTaskName = reviewTcProperties[0].getDisplayValue();
									System.out.println("aliasTaskName:" + aliasTaskName);
									if (aliasTaskName.contains(":")) {
										String reviewNodeName = aliasTaskName.split(":")[0].trim();
										System.out.println("reviewNodeName:" + reviewNodeName);
										System.out.println("reviewName:" + reviewName);
										if (reviewNodeName.equals(reviewName)) {
											assignee = reviewTcProperties[4].getDisplayValue();
											assigneeGroup = reviewTcProperties[2].getDisplayableValue();
											System.out.println("岗位组：" + assigneeGroup);
											TCProperty assigneeProperty = reviewTcProperties[3];
											if (assigneeProperty.getDisplayValue().length() > 0) {
												assigner = assigneeProperty.getDisplayValue();
											} else {
												assigner = assignee;
											}

											row.getCell(4).setCellValue(assigner);
											row.getCell(6).setCellValue(assignee);
											row.getCell(7).setCellValue(assigneeGroup);
										}
									}
									status = workflowTcProperties[4].getDisplayValue().equals("已完成") ? "已完成" : "未完成";

									row.getCell(16).setCellValue(status);
									endDateValue = workflowTcProperties[2].getDisplayValue();
									Date startDate = workflowTcProperties[3].getDateValue();

									assignStartDay = new SimpleDateFormat("yyyy-MM-dd").format(processStartDate);
									Date endDate = workflowTcProperties[2].getDateValue();
									actualHours = "" + (endDate.getTime() - startDate.getTime()) / 1000 / 3600;
									float point = (float) 0.0;

									row.getCell(12).setCellValue(actualHours);
									row.getCell(13).setCellValue(assignStartDay);
									row.getCell(15).setCellValue(endDateValue);
									if (status.equals("已完成")) {
										ZoneId zoneId = ZoneId.systemDefault();
										Instant instantEnd = endDate.toInstant();
//										Instant instantProcessEnd = processEndDate.toInstant();
										LocalDate localEndDate = instantEnd.atZone(zoneId).toLocalDate();
//										LocalDate localProcessEndDate = instantProcessEnd.atZone(zoneId).toLocalDate();
										// TODO 重新设定要求完成时间localEndDate
										String formation = requestTimeMap.get(cellBValue);
										System.out.println("formation:" + formation);
										Date formateDate = null;
										if (formation.contains("E")) {
											formateDate = processStartDate;
										} else if (formation.contains("F")) {
											formateDate = processEndDate;
										}
										Instant instantFormateDate = formateDate.toInstant();
										LocalDate localFormateDate = instantFormateDate.atZone(zoneId).toLocalDate();
										if (formation.contains("+")) {
											long daysToAdd = Long.valueOf(formation.split("+")[1]);
											System.out.println("daysToAdd:" + daysToAdd);
											localFormateDate = localFormateDate.plusDays(daysToAdd);
										} else if (formation.contains("-")) {

											long daysToMinus = Long.valueOf(formation.split("-")[1]);
											System.out.println("前：" + localFormateDate);
											localFormateDate = localFormateDate.minusDays(daysToMinus);
											System.out.println("后：" + localFormateDate);
											System.out.println("daysToMinus:" + daysToMinus);
										}
										requestEndDay = new SimpleDateFormat("yyyy-MM-dd").format(
												Date.from(localFormateDate.atStartOfDay().atZone(zoneId).toInstant()));
										row.getCell(14).setCellValue(requestEndDay);
//										requestEndDay = sdf.format(Date.from(instantFormateDate));
										long diff = localEndDate.toEpochDay() - localFormateDate.toEpochDay();
										System.out.println("diff:" + diff);
										String overtimeCoefficient = "";// 扣分系数
										postCoefficient = postCoefficientMap.get(assigneeGroup);
										for (Map.Entry<String, String> me : severityIntervalMap.entrySet()) {
											String interval = me.getKey();
											System.out.println("interval:" + interval);
											String startDay = interval.split(",")[0];
											String endDay = interval.split(",")[1];
											boolean condition1 = false;
											boolean condition2 = false;
											if (startDay.startsWith("[")) {
												int startInt = Integer
														.valueOf(startDay.substring(1, startDay.length()));
												System.out.println("startInt:" + startInt);
												condition1 = diff >= startInt ? true : false;
											} else if (startDay.startsWith("(")) {
												int startInt = Integer
														.valueOf(startDay.substring(1, startDay.length()));
												System.out.println("startInt:" + startInt);
												condition1 = diff > startInt ? true : false;
											}
											if (endDay.endsWith("]")) {
												int endInt = Integer.valueOf(endDay.substring(0, endDay.length() - 1));
												System.out.println("endInt:" + endInt);
												condition2 = diff <= endInt ? true : false;
											} else if (endDay.endsWith(")")) {
												int endInt = Integer.valueOf(endDay.substring(0, endDay.length() - 1));

												System.out.println("endInt:" + endInt);
												condition2 = diff < endInt ? true : false;
											}
											if (condition1 == true && condition2 == true) {
												overtimeCoefficient = me.getValue();
											} else {
												continue;
											}
										}
										System.out.println("overtimeCoefficient:" + overtimeCoefficient);
										System.out.println("postCoefficient:" + postCoefficient);
										System.out.println("taskNatureCoefficient:" + taskNatureCoefficient);
										System.out.println("taskDifficultyCoefficient:" + taskDifficultyCoefficient);
										System.out.println("urgencyCoefficient:" + urgencyCoefficient);
										if (!overtimeCoefficient.equals("")) {
											point = 1 * Float.valueOf(overtimeCoefficient)
													* Float.valueOf(postCoefficient)
													* Float.valueOf(taskNatureCoefficient)
													* Float.valueOf(taskDifficultyCoefficient)
													* Float.valueOf(urgencyCoefficient);
											deductPoints = point + "";
											
											
											row.getCell(17).setCellValue(deductPoints);
										}
									}
								}
							}
						}
					} catch (TCException e) {
						e.printStackTrace();
					}
				}
			} else {
				continue;
			}
		}
		// 导出
		String fileName = "绩效报表" + sdf.format(new Date()) + ".xlsx";
		filePath = filePath + File.separator + fileName;
		try {
			FileOutputStream os = new FileOutputStream(filePath);
			workbook.write(os);
			os.close();
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		wait.setBool(true);
		wait.interrupt();
		MessageBox.post("完成，详见：" + filePath, "", MessageBox.INFORMATION);

	}

	/**
	 * 通过数据方式获取工艺结束时间
	 * 
	 * @throws SQLException
	 * @throws ParseException
	 */
	private void getProcessTime(String targetName) throws SQLException, ParseException {
		String[] ldSqlServer = session.getPreferenceService().getStringValues("ld_sqlserver");
		String databaseName = ldSqlServer[0];
		String databasePassword = ldSqlServer[1];
		String databaseUrl = ldSqlServer[2];
		String databaseDriver = ldSqlServer[3];
		String tableName = ldSqlServer[4];
		SqlUtil.getConnection(databaseName, databasePassword, databaseUrl, databaseDriver);
		String searchQuestion = "";

		String folderName = targetName;
		searchQuestion = SqlUtil.getSelectSql_1(tableName, "proj_cus_prod_folder", folderName);
		ResultSet set = SqlUtil.read(searchQuestion);// 执行语句
		System.out.println(searchQuestion);
		set = SqlUtil.read(searchQuestion);// 执行语句
		String projProgEnd = "";
		String projProgStart = "";
		if (set.next()) {
			projProgEnd = set.getString("proj_prog_end");// 工艺程序结束 字符串存储，格式：2023/12/14
			projProgStart = set.getString("proj_prog_start");// 工艺程序开始 字符串存储，格式：2023/12/14
		}

		// 关闭数据库
		SqlUtil.freeAll();//
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		processStartDate = sdf.parse(projProgStart);
		processEndDate = sdf.parse(projProgEnd);
	}

	/**
	 * 检查首选项是否设置
	 * 
	 * @param preferenceValue 首选项值
	 * @param preferenceName  首选项名称
	 * @return 没有配置就返回false
	 */
	private boolean getMessageInfo(String[] preferenceValue, String preferenceName) {
		if (preferenceValue == null || preferenceValue.length == 0) {
			MessageBox.post("请通知管理员检查首选项" + preferenceName + "是否配置", "", MessageBox.INFORMATION);
			return false;
		}
		return true;
	}

	/**
	 * 检查首选项是否设置
	 * 
	 * @param preferenceValue 首选项值
	 * @param preferenceName  首选项名称
	 * @return 没有配置就返回false
	 */
	private boolean getMessageboxInfo(String preferenceValue, String preferenceName) {
		if (preferenceValue == null || preferenceValue.length() == 0) {
			MessageBox.post("请通知管理员检查首选项" + preferenceName + "是否配置", "", MessageBox.INFORMATION);
			return false;
		}
		return true;
	}

	/**
	 * 循环便利项目文件夹下的所有文件夹，并添加到集合和map中
	 * 
	 * @param target       文件夹
	 * @param path         文件路径
	 * @param link         连接符
	 * @param taskPathList 任务包路径集合
	 * @param folderMap    任务包路径，任务包对象
	 */
	private void getAllFolderPath(TCComponent target, String path, String link, List<String> taskPathList,
			Map<String, TCComponent> folderMap) {
		try {
			TCComponent[] contents = target.getRelatedComponents("contents");
			for (int i = 0; i < contents.length; i++) {
				TCComponent content = contents[i];
				String contentType = content.getType();
				String mergePath = "";
				if (contentType.equals("LD6_ProjMaFolder")) {

					TCComponent[] childContents = content.getRelatedComponents("contents");

					if (path.length() > 0) {
						mergePath = path + link;
					}
					mergePath = mergePath + content.getProperty("object_name");
					if (childContents.length > 0) {
						getAllFolderPath(content, mergePath, link, taskPathList, folderMap);
					} else {
						taskPathList.add(mergePath);
						System.out.println("mergePath:" + mergePath);
						folderMap.put(mergePath, content);
					}
				}
			}
		} catch (TCException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 下载文件
	 * 
	 * @param 数据集对象
	 * @return 下载的命名引用文件
	 */
	public String downLoadFile(TCComponent comp) {
		if (comp == null) {
			return "";
		}
		String value = "";
		String tempPath = System.getenv("TEMP");
		if (tempPath == null) {
			tempPath = "";
		} else if (!tempPath.endsWith("\\")) {
			tempPath = tempPath + "\\";
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
		try {
			if (comp instanceof TCComponentDataset) {
				TCComponentTcFile[] tcFiles = ((TCComponentDataset) comp).getTcFiles();
				File file = null;
				System.out.println("tcFiles:" + tcFiles.length);
				if (tcFiles != null && tcFiles.length != 0) {
					file = tcFiles[0].getFmsFile();
					String fileName = file.getName();
					System.out.println("fileName:" + fileName);
					String fileDix = fileName.substring(fileName.lastIndexOf("."), fileName.length());
					fileName = tempPath + sdf.format(new Date()) + fileDix;
					File dirFile = new File(fileName);
					FileUtility.copyFile(file, dirFile);
					return fileName;
				}
			}
		} catch (TCException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return value;
	}

}
