/**
 * Copyright &copy; 2012-2014 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.cku.oa.show.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.validation.Validator;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.cku.core.ZAErrorCode;
import com.cku.core.ZAException;
import com.cku.oa.finance.entity.PaymentChargingItem;
import com.cku.oa.finance.service.PaymentChargingItemService;
import com.cku.oa.show.dao.ChildShowsDao;
import com.cku.oa.show.dao.ShowApplyDao;
import com.cku.oa.show.entity.ChildShows;
import com.cku.oa.show.entity.MainShows;
import com.cku.oa.show.entity.ShowMainJudgeInfo;
import com.thinkgem.jeesite.common.beanvalidator.BeanValidators;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.service.CrudService;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.common.utils.excel.ImportExcel;
import com.thinkgem.jeesite.modules.sys.utils.DictUtils;

/**
 * 犬展子表Service
 * 
 * @author lgl
 * @version 2016-07-13
 */
@Service
@Transactional(readOnly = true)
public class ChildShowsService extends CrudService<ChildShowsDao, ChildShows> {

	/**
	 * 验证Bean实例对象
	 */
	@Autowired
	protected Validator validator;

	@Autowired
	private MainShowsService mainShowsService;
	@Autowired
	private PaymentChargingItemService paymentChargingItemService;
	@Autowired
	private ShowApplyDao showApplyDao;
	@Autowired
	private ShowMainJudgeInfoService showMainJudgeInfoService;

	public ChildShows get(String id) {
		ChildShows childShows = super.get(id);
		return childShows;
	}

	public ChildShows getByShowCode(String showCode) {
		return dao.getByShowCode(showCode);
	}

	public List<ChildShows> findList(ChildShows childShows) {
		return super.findList(childShows);
	}

	public Page<ChildShows> findPage(Page<ChildShows> page, ChildShows childShows) {
		Page<ChildShows> childShowsPage = super.findPage(page, childShows);
		if (CollectionUtils.isNotEmpty(childShowsPage.getList())) {
			for (ChildShows shows : childShowsPage.getList()) {
				shows.setShowName(StringEscapeUtils.unescapeHtml4(shows.getShowName()));
			}
		}
		return super.findPage(page, childShows);
	}

	@Transactional(readOnly = false)
	public void save(ChildShows childShows) {
		super.save(childShows);
	}

	@Transactional(readOnly = false)
	public void delete(ChildShows childShows) {
		super.delete(childShows);
	}

	/**
	 * 获取所有犬展编号
	 * 
	 * @return
	 */
	public List<String> findShowCodeList(String showRules) {
		return dao.findShowCodeList(showRules);
	}

	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void saveMainShows(MainShows mainShows) throws Exception {
		Date isTopTime = null;
		if("1" .equals(mainShows.getIsTop()) ) {
			if(StringUtils.isNotBlank(mainShows.getId())) {
				MainShows mainShowsOld = mainShowsService.get(mainShows.getId());
				if(!Objects.isNull(mainShowsOld)  &&  !"1" .equals(mainShowsOld.getIsTop()) ) {
					isTopTime = com.cku.util.DateUtils.getNow();
				}
			}else {
				isTopTime = com.cku.util.DateUtils.getNow();
			}
		}
		mainShows.setIsTopTime(isTopTime);
		// 设置主犬展的开始、结束时间
		setMainShowStartEndTime(mainShows);
		mainShowsService.save(mainShows);
		for (ChildShows childShows : mainShows.getChildShowsList()) {
			childShows.setMainShowId(mainShows.getId());
			if (StringUtils.isBlank(childShows.getStatisticsState())) {
				childShows.setStatisticsState("0");
			}
			// 犬展标号查重
			if (dao.getByShowCodeAndId(childShows) != null) {
				throw new ZAException(ZAErrorCode.ZA_VALID_FAILED,
						"已有犬展编号为" + childShows.getShowCode() + "的犬展信息，请勿重复添加！");
			}

			// 增加删除子犬展条件判断，如果已经有报名，则不允许删除
			if ("1".equals(childShows.getDelFlag()) && showApplyDao
					.countByShowMainIdAndShowCode(childShows.getMainShowId(), childShows.getShowCode()) > 0) {
				throw new ZAException(ZAErrorCode.ZA_VALID_FAILED,
						"无法删除犬展编号为" + childShows.getShowCode() + "的子犬展，已存在报名信息！");
			}
			// 增加判断如果修改比赛编号需要验证没有有效报名
			if (StringUtils.isNotBlank(childShows.getId())) {
				ChildShows old = super.get(childShows.getId());
				if (old != null && !Objects.equals(old.getShowCode(), childShows.getShowCode())) {
					if (showApplyDao.getListByShowCode(old.getShowCode()).size() > 0) {
						throw new ZAException(ZAErrorCode.ZA_VALID_FAILED,
								"犬展编号" + old.getShowCode() + "存在有效报名记录，如需修改请联系技术！");
					}
				}
			}
			
			super.save(childShows);
		}
		// 保存裁判照片
		if ("2".equals(mainShows.getIsShowType())) {
			// 查出原来的裁判列表
			List<ShowMainJudgeInfo> oldList = showMainJudgeInfoService.findListByShowMainId(mainShows.getId());
			// 新的list含有哪些旧元素
			List<String> newIds = mainShows.getJudgeInfoList().stream().filter(a -> StringUtils.isNotBlank(a.getId()))
					.map(ShowMainJudgeInfo::getId).collect(Collectors.toList());
			// 删除
			oldList.stream().filter(a -> !newIds.contains(a.getId())).forEach(a -> {
				showMainJudgeInfoService.delete(a);
			});

			for (ShowMainJudgeInfo judgeInfo : mainShows.getJudgeInfoList()) {
				if (StringUtils.isNotBlank(judgeInfo.getShowJudgeId())) {// 过滤空元素
					judgeInfo.setShowMainId(mainShows.getId());
					showMainJudgeInfoService.save(judgeInfo);
				}
			}
		}

	}

	/**
	 * 设置主犬展的开始、结束时间
	 * 
	 * @param mainShows
	 * @throws ZAException
	 */
	private void setMainShowStartEndTime(MainShows mainShows) throws ZAException {
		Date startTime = null;
		Date endTime = null;
		ChildShows childShows = null;
		List<ChildShows> childShowsList = mainShows.getChildShowsList();
		for (int i = 0; i < childShowsList.size(); i++) {
			childShows = childShowsList.get(i);
			// 校验结束时间必须大于开始时间
			if (childShows.getStartTime().after(childShows.getEndTime())) {
				throw new ZAException(ZAErrorCode.ZA_VALID_FAILED,
						"犬展代码为" + childShows.getShowCode() + "的活动开始时间大于结束时间");
			}
			if (i == 0) {
				startTime = childShows.getStartTime();
				endTime = childShows.getEndTime();
			} else {
				if (startTime.after(childShows.getStartTime())) {
					startTime = childShows.getStartTime();
				}
				if (endTime.before(childShows.getEndTime())) {
					endTime = childShows.getEndTime();
				}
			}
		}
		mainShows.setStartTime(startTime);
		mainShows.setEndTime(endTime);
	}

	public List<ChildShows> findChildShowsByMainShowId(String mainShowId) {
		ChildShows childShows = new ChildShows();
		childShows.setMainShowId(mainShowId);
		List<ChildShows> list = super.findList(childShows);
		// 根据犬展编号进行排序
		Collections.sort(list, new Comparator<ChildShows>() {
			public int compare(ChildShows o1, ChildShows o2) {
				return o1.getShowCode().compareTo(o2.getShowCode());
			}
		});
		return list;
	}

	/**
	 * 对子犬展进行分组
	 * 
	 * @param list
	 * @return
	 */
	private Map<String, List<ChildShows>> groupingChildShows(List<ChildShows> list) throws Exception {
		Map<String, List<ChildShows>> map = new HashMap<String, List<ChildShows>>();
		String mainShowCode = null;
		List<ChildShows> childShowsList = null;
		for (int i=0;i<list.size();i++) {
			ChildShows childShows = list.get(i);
			// 跳过无效记录
			if (childShows == null || StringUtils.isBlank(childShows.getShowCode())
					|| childShows.getShowCode().length() < 6) {
				continue;
			}
			mainShowCode = childShows.getShowCode().substring(0, 7);
			// 参数校验
			try {
				BeanValidators.validateWithException(validator, childShows);
			} catch (Exception e) {
				logger.info("参数校验出错", e);
				throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "参数有误，请修改后再导入！");
			}
			// 字典字段进行转换
			String organizer = DictUtils.getDictValue(childShows.getOrganizer(), "show_organizer_2023", "");
			if (StringUtils.isBlank(organizer)) {
				throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "第"+i+"行主办单位有误，请修改后再导入！");
			}
			childShows.setOrganizer(organizer);
			String orgnizeType = childShows.getOrgnizeType();
			
			if ( !( "自办".equals(orgnizeType) || "合办新模式".equals(orgnizeType)|| "合办新模式2025".equals(orgnizeType))) {
				throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "第"+i+"行举办方式有误，请修改后再导入！");
			}
			
			if ("合办新模式2025".equals(orgnizeType)&&"1".equals(organizer)) {
				throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "第"+i+"行主办单位有误，合办新模式2025不支持主办单位为CKU犬展，请修改后再导入！");
			}
			
			if ("合办新模式2025".equals(orgnizeType)) {
				childShows.setOrgnizeType("3");
				childShows.setBusinessModelFlag(DictUtils.getDictValue(orgnizeType.substring(2, 5),
						"business_model_flag", ""));
			} else if (orgnizeType.contains("合办")) {
				childShows.setOrgnizeType("0");
				childShows.setBusinessModelFlag(DictUtils.getDictValue(orgnizeType.substring(2, orgnizeType.length()),
						"business_model_flag", ""));
			} else {
				childShows.setOrgnizeType("1");
			}
			
			childShows.setShowRules(DictUtils.getDictValue(childShows.getShowRules(), "show_rules", ""));
			if(StringUtils.isBlank(childShows.getShowRules())) {
				throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "第"+i+"行规则有误，请修改后再导入！");
			}
			if ("CAC".equals(childShows.getCacType())) {
				childShows.setCacType("0");
			} else if ("CACIB".equals(childShows.getCacType())) {
				childShows.setCacType("1");
			}else {
				throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "第"+i+"行CAC类型(BBE相关)有误，请修改后再导入！");
			}
			// 分组
			childShowsList = map.get(mainShowCode);
			if (childShowsList == null) {
				childShowsList = new ArrayList<ChildShows>();
				childShowsList.add(childShows);
				map.put(mainShowCode, childShowsList);
			} else {
				childShowsList.add(childShows);
			}
			// 优惠卷字段进行转换
			String useCoupon = childShows.getUseCoupon();
			if (useCoupon.contains("是")) {
				childShows.setUseCoupon("0");
			} else {
				childShows.setUseCoupon("1");
			}
			childShows.setIsDiscount("1");
		}
		return map;
	}

	/**
	 * 组装对象并写数据库
	 * 
	 * @param map
	 * @throws Exception
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void saveMainShows(Map<String, List<ChildShows>> map) throws Exception {
		try {
			List<ChildShows> childShowsList = null;
			ChildShows childShows = null;
			MainShows mainShows = null;
			for (Entry<String, List<ChildShows>> entry : map.entrySet()) {
				childShowsList = entry.getValue();
				childShows = childShowsList.get(0);
				mainShows = new MainShows();
				mainShows.setShowLocation(childShows.getShowLocation());
				mainShows.setMainShowName(childShows.getMainShowName());
				mainShows.setClosingTime(childShows.getClosingTime());
				mainShows.setOrganizer(childShows.getOrganizer());
				mainShows.setOrgnizeType(childShows.getOrgnizeType());
				mainShows.setBusinessModelFlag(childShows.getBusinessModelFlag());
				mainShows.setDogNumMax(childShows.getDogNumMax());
				mainShows.setBranchShowDetail(childShows.getBranchShowDetail());
				mainShows.setAttention(childShows.getAttention());
				mainShows.setRegister(childShows.getRegister());
				mainShows.setYear(childShows.getYear());
				mainShows.setChildShowsList(childShowsList);
				saveMainShows(mainShows);
			}
		} catch (Exception e) {
			logger.warn("导入犬展信息出错", e);
			throw new ZAException(ZAErrorCode.ZA_VALID_FAILED, "导入犬展信息出错:" + e.getMessage());
		}
	}

	/**
	 * 犬展信息导入
	 * 
	 * @param
	 * @throws Exception
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void importShows(MultipartFile file) throws Exception {
		ImportExcel ei = new ImportExcel(file, 0, 0);
		List<ChildShows> list = ei.getDataList(ChildShows.class);
		// 对子犬展进行分组
		Map<String, List<ChildShows>> map = groupingChildShows(list);
		// 组装对象并写数据库
		saveMainShows(map);
	}

	public String getShowFeeTemplate() {
		List<PaymentChargingItem> list = paymentChargingItemService.getByShortNamePrefix("show_apply@fee");
		StringBuilder sb = new StringBuilder("<option value=''>请选择</option>");
		for (PaymentChargingItem item : list) {
			sb.append("<option value='" + item.getId() + "'>" + item.getPrice() + item.getName() + "</option>");
		}
		return sb.toString();
	}

	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public int setSerialNumber() {
		Integer maxSerialNumber = dao.getMaxSerialNumber();
		return dao.setSerialNumber(maxSerialNumber);
	}

	/**
	 * @Description 修改赛场成绩状态
	 * @author yuanshuai
	 * @date 2020/11/13 14:52
	 */
	@Transactional(readOnly = false)
	public int updateWinnerState(ChildShows childShows) {
		childShows.preUpdate();
		return dao.updateWinnerState(childShows);
	}

	public List<ChildShows> find51List() {
		return dao.find51List();
	}

	/**
	 *
	 * @description: 标记该犬展为未统计
	 * @author: laiguanglong
	 * @date: 2016年11月30日 下午4:21:23
	 */
	@Transactional(readOnly = false)
	public void updateUnStatisticsState(String showCode) {
		// 更新本场犬展成绩更新状态
		ChildShows childShows = dao.getByShowCode(showCode);
		String statisticsState = null;
		if ("0".equals(childShows.getStatisticsState())) {
			statisticsState = "0";
		} else if (!"0".equals(childShows.getStatisticsState())) {
			statisticsState = "2";
		}
		childShows.setStatisticsState(statisticsState);
		dao.update(childShows);
	}
	
	
	public List<ChildShows> findListByMainShowId(String mainShowId) {
		return dao.getByMainShowId(mainShowId);
	}

}