/**
* 文件：AssetServiceImpl.java
* 版本：1.0.0
* 日期：
* Copyright &reg; 
* All right reserved.
*/

package com.mortals.xhx.module.asset.service.impl;

import com.mortals.framework.common.code.YesNo;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.IUser;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.framework.util.DateUtils;
import com.mortals.framework.util.StringUtils;
import com.mortals.xhx.base.system.upload.service.UploadService;
import com.mortals.xhx.module.api.model.AssetEventLog;
import com.mortals.xhx.module.api.service.AssetFlowStatusService;
import com.mortals.xhx.module.asset.dao.AssetDao;
import com.mortals.xhx.module.asset.model.AssetEntity;
import com.mortals.xhx.module.asset.model.AssetFlowEventLogEntity;
import com.mortals.xhx.module.asset.model.AssetQuery;
import com.mortals.xhx.module.asset.service.AssetFlowEventLogService;
import com.mortals.xhx.module.asset.service.AssetService;
import com.mortals.xhx.module.materia.model.MateriaBomEntity;
import com.mortals.xhx.module.materia.model.MateriaEntity;
import com.mortals.xhx.module.materia.service.MateriaBomService;
import com.mortals.xhx.module.materia.service.MateriaService;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * Title: 资产表
 * </p>
 * <p>
 * Description: AssetServiceImpl service接口
 * </p>
 * <p>
 * Copyright: Copyright &reg;
 * </p>
 * <p>
 * Company:
 * </p>
 * 
 * @author
 * @version 1.0.0
 */
@Service("assetService")
public class AssetServiceImpl extends AbstractCRUDServiceImpl<AssetDao, AssetEntity, Long> implements AssetService {

	@Resource
	private UploadService uploadService;
	@Autowired
	private MateriaService materiaService;
	@Autowired
	private AssetFlowStatusService assetFlowStatusService;
	@Autowired
	private AssetFlowEventLogService assetFlowEventLogService;


	@Autowired
	private MateriaBomService materiaBomService;

	@Override
	public AssetEntity getByAssetNum(String assetNum) {
		AssetQuery query = new AssetQuery();
		query.setAssetNum(assetNum);
		List<AssetEntity> assetEntityList = this.find(query, null);
		return assetEntityList.isEmpty() ? null : assetEntityList.get(0);
	}

	@Override
	public Map<String, Object> saveImport(AssetEntity deviceEntity, String filePath, IUser user) {
		Map<String, Object> result = new HashMap<>();

		int errorNumber = 0;
		int successNumber = 0;
		int exceptionCount = 0;
		List<String> errRows = new ArrayList<>();
		XSSFWorkbook xssfWorkbook = null;
		File file = null;
		try {
			file = new File(uploadService.getFilePath(filePath));
			xssfWorkbook = new XSSFWorkbook(new FileInputStream(file));
			XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(0);
			if (xssfSheet != null) {
				Context context = new Context();
				context.setUser(user);
				Date createTime = new Date();

				for (int rowNum = 1; rowNum <= xssfSheet.getLastRowNum(); rowNum++) {
					try {
						XSSFRow xssfRow = xssfSheet.getRow(rowNum);
						AssetEntity entity = new AssetEntity();

						String assetNum = getValue(xssfRow.getCell(0), 0);
						if (StringUtils.isEmpty(assetNum) || assetNum.length() != 16) {
							errorNumber++;
							errRows.add("第" + rowNum + "行资产码为空或长度小于不等于16位");
							continue;
						}
						if (this.getByAssetNum(assetNum) != null) {
							errorNumber++;
							errRows.add("第" + rowNum + "行资产码已存在");
							continue;
						}

						entity.setAssetNum(assetNum);
						entity.setDeviceNum(getValue(xssfRow.getCell(1), 0)); // 业务码
						String bomIdStr = getValue(xssfRow.getCell(2),0 );
						if (StringUtils.isEmpty(bomIdStr)) {
							errorNumber++;
							errRows.add("第" + rowNum + "行BOM ID为空;");
							continue;
						}
						MateriaBomEntity bomEntity = materiaBomService.get(Long.valueOf(bomIdStr), null);
						if(bomEntity == null){
							errorNumber++;
							errRows.add("第" + rowNum + "行BOM ID有误，Bom不存在;");
							continue;
						}
						if(StringUtils.isEmpty(bomEntity.getVersion())){
							errorNumber++;
							errRows.add("第" + rowNum + "行BOM ID有误，Bom 版本不存在;");
							continue;
						}
						MateriaEntity materiaEntity = materiaService.get(bomEntity.getMateriaId(), null);
						if(assetNum.substring(0,2).equals(materiaEntity.getAssetsCode())){
							errorNumber++;
							errRows.add("第" + rowNum + "行资产码有误，前两位必须为所选BOM对应资产编码;");
							continue;
						}

						entity.setBomId(bomEntity.getId());//bom id
						entity.setMateriaId(bomEntity.getMateriaId()); //物料ID通过bom id获得
						entity.setMateriaCode(bomEntity.getMateriaCode());

						String producerIdStr = getValue(xssfRow.getCell(3), 0);
						if (StringUtils.isEmpty(producerIdStr)) {
							errorNumber++;
							errRows.add("第" + rowNum + "行生产厂家ID为空");
							continue;
						}
						entity.setProducerId(Long.valueOf(producerIdStr)); //生产厂家

						String producerCostStr = getValue(xssfRow.getCell(4), 2);
						if (StringUtils.isEmpty(producerCostStr)) {
							errorNumber++;
							errRows.add("第" + rowNum + "行生产成本为空");
							continue;
						}
						entity.setProduceCost(new BigDecimal(producerCostStr).multiply(new BigDecimal("1000")).longValue()); //生产成本(转成厘）

						String producerDateStr = getValue(xssfRow.getCell(5), 0);
						if (StringUtils.isEmpty(producerIdStr)) {
							errorNumber++;
							errRows.add("第" + rowNum + "行生产日期为空");
							continue;
						}
						entity.setProduceDate(DateUtils.StrToDateTime(producerDateStr, DateUtils.P_yyyyMMdd)); //生产日期


						String flowStatusStr = getValue(xssfRow.getCell(6), 0);
						if (StringUtils.isEmpty(flowStatusStr)) {
							errorNumber++;
							errRows.add("第" + rowNum + "行流转状态为空");
							continue;
						}
						entity.setBeforeFlowStatus(Integer.valueOf(flowStatusStr));
						entity.setFlowStatus(Integer.valueOf(flowStatusStr)); // 流转状态
						entity.setEnabled(
								"启用".equals(getValue(xssfRow.getCell(7), 0)) ? YesNo.YES.getValue() : YesNo.NO.getValue()); // 生产者ID

						// 操作人信息
						entity.setCreateUserId(user.getId());
						entity.setCreateUser(user.getLoginName());
						entity.setCreateUserName(user.getRealName());
						entity.setCreateUserDeptId(user.getDeptId());
						entity.setCreateUserDeptName(user.getDeptName());
						entity.setCreateTime(createTime);
						entity.setUpdateUserId(user.getId());
						entity.setUpdateUser(user.getLoginName());
						entity.setUpdateUserDeptId(user.getDeptId());
						entity.setUpdateUserDeptName(user.getDeptName());
						entity.setUpdateTime(entity.getCreateTime());

						this.dao.insert(entity);
						//导入不写日志
						/*// 写日志
						this.saveEventLog(entity, context);*/
						successNumber++;
					} catch (Exception e) {
						if (exceptionCount == 0) {
							log.error("导入异常", e);
						}
						exceptionCount++;
						errorNumber++;
						errRows.add("第" + rowNum + "行异常;");
					}
				}
			}
		} catch (IOException e) {
			log.error("读取导入文件出错", e);
		} finally {
			// 删除上传的文件
			file.delete();
			/*
			 * if (xssfWorkbook != null) { try { xssfWorkbook.close(); } catch (IOException
			 * e) { log.error("读取导入文件出错", e); } }
			 */
		}

		result.put("successNumber", successNumber);
		result.put("errorNumber", errorNumber);
		result.put("errRows", errRows);
		log.info(String.format(
				"导入完成，总共导入：%d条，成功：%d条，失败：%d条. " + (errRows.size() > 0 ? " 失败详情:" + errRows.toString() : ""),
				successNumber + errorNumber, successNumber, errorNumber));
		return result;

	}

	private String getValue(XSSFCell xssfCell, int numberScale) {
		String value = null;
		if (xssfCell != null) {
			switch (xssfCell.getCellType()) {
/*			case XSSFCell.CELL_TYPE_BOOLEAN:
				// 处理字符串单元格
				value = String.valueOf(xssfCell.getBooleanCellValue());
				break;
			case XSSFCell.CELL_TYPE_NUMERIC:
				// 处理数字或日期单元格
				if (DateUtil.isCellDateFormatted(xssfCell)) {
					Date date = xssfCell.getDateCellValue();
					if (date != null) {
						value = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(date);
					} else {
						value = "";
					}
				} else {
					value = new BigDecimal(String.valueOf(xssfCell.getNumericCellValue())).setScale(numberScale).toString();
				}
				break;*/
			default:
				value = xssfCell.getStringCellValue().trim();
			}
		} else {
			value = "";
		}
		return value;
	}

//	private Date getDate(XSSFCell xssfCell) {
//		if (xssfCell != null) {
//			if (xssfCell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC) {
//				if (DateUtil.isCellDateFormatted(xssfCell)) {
//					return xssfCell.getDateCellValue();
//				}
//			}
//			return DateUtils.StrToDateTime(xssfCell.getStringCellValue().trim());
//		}
//		return null;
//	}

	@Override
	protected void saveBefore(List<AssetEntity> list, Context context) throws AppException {
		super.saveBefore(list, context);
		for (AssetEntity assetEntity : list) {
			assetEntity.setBeforeFlowStatus(assetEntity.getFlowStatus());
		}
	}

	@Override
	protected void saveAfter(List<AssetEntity> list, Context context) throws AppException {
		super.saveAfter(list, context);
		// 写事件日志
		for (AssetEntity entity : list) {
			saveEventLog(entity, context);
		}
	}

	@Override
	protected void saveAfter(AssetEntity entity, Context context) throws AppException {
		super.saveAfter(entity, context);
		// 写事件日志
		saveEventLog(entity, context);
	}

	@Override
	protected void saveBefore(AssetEntity entity, Context context) throws AppException {
		super.saveBefore(entity, context);
		entity.setBeforeFlowStatus(entity.getFlowStatus());
	}

	@Override
	protected void validData(AssetEntity entity, Context context) throws AppException {

		//新增时校验资产码(因为资产码新建后不可修改，所有只校验新增）
		if (entity.getId() == null) {
			// 校验资产码是否已被使用
			AssetQuery assetQuery = new AssetQuery();
			assetQuery.setAssetNum(entity.getAssetNum());
			List<AssetEntity> existList = this.dao.getList(assetQuery);
			if (!existList.isEmpty()) {
				throw new AppException("资产码已被使用");
			}
			//暂时BOM相关的信息可以为空
			if(entity.getMateriaId() != null){
				//检验资产码的前两位和选择的物料前两位是否相等
				MateriaEntity materiaEntity = materiaService.get(entity.getMateriaId(), context);
				if(materiaEntity == null){
					throw new AppException("所选Bom物料不存在");
				}
				if(StringUtils.isEmpty(materiaEntity.getAssetsCode())){
					throw new AppException("所选Bom物料资产编码字段为空，请先前往【物料模块】补充对应对应物料的资产编码字段");
				}
				if(!entity.getAssetNum().substring(0,2).equals(materiaEntity.getAssetsCode())){
					throw new AppException("资产码有误，前两位必须为所选BOM对应资产编码：" + materiaEntity.getAssetsCode());
				}
			}


		}
		super.validData(entity, context);
	}

	private void saveEventLog(AssetEntity entity, Context context) {
		// 写事件日志
		AssetEventLog log = new AssetEventLog();
		log.setAssetNumList(new ArrayList<String>() {
			{
				add(entity.getAssetNum());
			}
		});
		log.setEventAddress("新增");
		log.setEventAfterUser("");
		log.setEventCode("101");// 101：资产码生成事件
		log.setEventExtInfo(null);
		log.setEventImgUrl("无");
		log.setEventTime(entity.getCreateTime());
		log.setEventUser(context.getUser().getLoginName());
		log.setRemark(null);
		assetFlowStatusService.execute(log);
	}

	/**
	 * 接口初始化资产
	 * @param entity
	 */
	@Transactional
	@Override
	public void initEntity(AssetEntity entity) {
		AssetQuery assetQuery = new AssetQuery();
		assetQuery.setAssetNum(entity.getAssetNum());
		if(this.dao.getCount(assetQuery) >0){
			throw new AppException("资产码已存在");
		}

		//根据Bom id查询bom和物料相关信息
		if(entity.getBomId() != null){
			MateriaBomEntity materiaBomEntity = materiaBomService.get(entity.getBomId(), null);
			entity.setMateriaId(materiaBomEntity.getMateriaId());
			entity.setMateriaCode(materiaBomEntity.getMateriaCode());
		}

		this.dao.insert(entity);

		//手动触发巡检事件日志
		AssetFlowEventLogEntity assetFlowEventLogEntity = new AssetFlowEventLogEntity();
		assetFlowEventLogEntity.setEventCode("123");
		assetFlowEventLogEntity.setAssetNum(entity.getAssetNum());
		assetFlowEventLogEntity.setBeforeStatus(entity.getBeforeFlowStatus());
		assetFlowEventLogEntity.setAfteStatus(entity.getFlowStatus());
		assetFlowEventLogEntity.setEventStartTime( new Date());
		assetFlowEventLogEntity.setEventTime(new Date());
		assetFlowEventLogEntity.setEventUser(entity.getCreateUser());
		assetFlowEventLogEntity.setEventAfterUser(entity.getCreateUser());
		assetFlowEventLogEntity.setEventAddress("无");
		assetFlowEventLogEntity.setEventImgUrl("无");

		assetFlowEventLogEntity.setRemark("运维扫码录入设备");
		assetFlowEventLogEntity.setCreateTime(new Date());

		assetFlowEventLogService.save(assetFlowEventLogEntity, null);

		/*AssetEventLog log = new AssetEventLog();
		log.setAssetNumList(new ArrayList<String>() {
			{
				add(entity.getAssetNum());
			}
		});
		log.setEventAddress("设备扫码录入");
		log.setEventAfterUser("");
		log.setEventCode("123");// 123：巡检事件
		log.setEventExtInfo(null);
		log.setEventImgUrl("无");
		log.setEventTime(entity.getCreateTime());
		log.setEventUser(entity.getCreateUser());
		log.setEventAfterUser(entity.getUpdateUser());
		log.setRemark("运维扫码录入设备");
		assetFlowStatusService.execute(log);*/

	}
}