package cn.hmsoft.skill.service.std;

import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.hmsoft.ai.identity.IdentifiedResult;
import cn.hmsoft.ai.identity.IdentityAI;
import cn.hmsoft.application.SpringHelper;
import cn.hmsoft.skill.constants.ArtDefaultValue;
import cn.hmsoft.skill.constants.ArtParamName;
import cn.hmsoft.skill.constants.StdCertType;
import cn.hmsoft.skill.constants.StdLogType;
import cn.hmsoft.skill.constants.StdMaterialType;
import cn.hmsoft.skill.constants.StdResType;
import cn.hmsoft.skill.data.model.cf.enrol.CfEnrolMaterial;
import cn.hmsoft.skill.data.model.std.StdMaterial;
import cn.hmsoft.skill.data.model.std.StdReg;
import cn.hmsoft.skill.data.model.std.StdRes;
import cn.hmsoft.skill.data.model.std.StdResLog;
import cn.hmsoft.skill.helper.EnrolMaterialHelper;
import cn.hmsoft.skill.helper.ArtParamHelper;
import cn.hmsoft.frame.constants.FrameStatus;
import cn.hmsoft.frame.data.model.FrameOptr;
import cn.hmsoft.frame.exception.BusinessException;
import cn.hmsoft.frame.util.FrameAssertUtil;
import cn.hmsoft.helper.BeanHelper;
import cn.hmsoft.helper.CollectionHelper;
import cn.hmsoft.helper.JsonHelper;
import cn.hmsoft.helper.StringHelper;
import cn.hmsoft.log.LogHelper;
import cn.hmsoft.skill.data.dao.std.EnrolStdResDao;
import cn.hmsoft.skill.data.dao.std.StdLogDao;
import cn.hmsoft.skill.data.dao.std.StdMaterialDao;
import cn.hmsoft.skill.data.dao.std.StdRegDao;

@Service
public class StdMaterialService {

	@Autowired
	private StdRegDao daoStd;
	@Autowired
	private StdLogDao daoLog;

	@Autowired
	private StdMaterialDao daoMaterial;
	@Autowired
	private EnrolStdResDao daoRes;

	private Map<String, Object> makeRandomMap(Map<String, Object> map, StdReg std) {
		map.put("StdReg", std);
		map.put("MaterialArray", this.daoMaterial.listAllMaterial(std.getStd_id()));
		return map;
	}
	

	public Map<String, Object> getRandomStd(String material_type, String query) {
		// 判断审核模式，
		String flag = ArtParamHelper.getParamValue(ArtParamName.EnrolMaterialVerifyWithPayed,
				FrameStatus.Active.toString());
		Map<String, Object> map = new HashMap<String, Object>();
		if(StringHelper.isNotEmpty(query)) {
			StdReg std = this.daoStd.findStdByQuery(query);
			FrameAssertUtil.isNotNull(std, "未找到考生，请检查输入的信息是否有误！");
			return makeRandomMap(map, std);
		}
		if (FrameStatus.Active.toString().equals(flag)) {
			// 先找审核过后重新上传的,且已经缴费的
			String sql = "select m.std_id from std_material m,std_enrol e where m.std_id=e.std_id and e.pay_status='Active' and material_type=? and verify_status is null and reupload_status='Active'   order by "
					+ daoStd.random();
			int pay_total = this.daoRes.findObject(Integer.class, "select count(1) from (" + sql + ") t",
					material_type);
			map.put("PayTotal", pay_total);
			if (pay_total > 0) {
				StdMaterial m = this.daoMaterial.listBySql(StdMaterial.class, 0, 1, sql, material_type).get(0);
				StdReg std = this.daoStd.findByStdId(m.getStd_id());
				if (std == null) {
					LogHelper.error("审核时，有考生材料，但未找到考生，考生编号【" + m.getStd_id() + "】");
				} else {
					return makeRandomMap(map, std);
				}
			}

			// 已经缴费，未审核
			sql = "select m.std_id from std_material m,std_enrol e where m.std_id=e.std_id and e.pay_status='Active' and material_type=? and verify_status is null and reupload_status is null  order by "
					+ daoStd.random();
			int noverify_total = this.daoRes.findObject(Integer.class, "select count(1) from (" + sql + ") t",
					material_type);
			map.put("NoVerifyTotal", noverify_total);
			if (noverify_total > 0) {
				StdMaterial m = this.daoMaterial.listBySql(StdMaterial.class, 0, 1, sql, material_type).get(0);
				StdReg std = this.daoStd.findByStdId(m.getStd_id());
				if (std == null) {
					LogHelper.error("审核时，有考生材料，但未找到考生，考生编号【" + m.getStd_id() + "】");
				} else {
					return makeRandomMap(map, std);
				}
			}
		} else {
			// 没有缴费的也要审核
			// 先找审核过后重新上传的,
			String sql = "select m.std_id from std_material m where material_type=? and verify_status is null and reupload_status='Active'   order by "
					+ daoStd.random();
			int pay_total = this.daoRes.findObject(Integer.class, "select count(1) from (" + sql + ") t",
					material_type);
			map.put("VerifyFailAndReupload", pay_total);
			if (pay_total > 0) {
				StdMaterial m = this.daoMaterial.listBySql(StdMaterial.class, 0, 1, sql, material_type).get(0);
				StdReg std = this.daoStd.findByStdId(m.getStd_id());
				if (std == null) {
					LogHelper.error("审核时，有考生材料，但未找到考生，考生编号【" + m.getStd_id() + "】");
				} else {
					return makeRandomMap(map, std);
				}
			}

			// 已经报考，未审核
			sql = "select m.std_id from std_material m where  material_type=? and verify_status is null and reupload_status is null  order by "
					+ daoStd.random();
			int noverify_total = this.daoRes.findObject(Integer.class, "select count(1) from (" + sql + ") t",
					material_type);
			map.put("NoVerify", noverify_total);
			if (noverify_total > 0) {
				StdMaterial m = this.daoMaterial.listBySql(StdMaterial.class, 0, 1, sql, material_type).get(0);
				StdReg std = this.daoStd.findByStdId(m.getStd_id());
				if (std == null) {
					LogHelper.error("审核时，有考生材料，但未找到考生，考生编号【" + m.getStd_id() + "】");
				} else {
					return makeRandomMap(map, std);
				}
			}

		}
		throw new BusinessException("没有需要审核的考生材料！");
	}

	public void checkNoCrownPhoto(FrameOptr optr, int std_id, StdMaterial material, String msg_flag) {
		StdReg std = this.daoStd.findByStdId(std_id);
		if (material == null)
			material = SpringHelper.getBean(StdMaterialDao.class).findMaterial(std.getStd_id(),
					StdMaterialType.NoCrownPhoto);
		if (material == null)
			throw new BusinessException("未找到免冠证件照图片，请重试！");
		File file = new File(EnrolMaterialHelper.getEnrolMaterialLocalPath() + material.getMaterial_file());
		if (!file.exists())
			throw new BusinessException("未找到免冠证件照图片，请重试！");

//		if (FrameStatus.Active.toString().equals(std.getStd_verify_flag())
//				|| FrameStatus.Active.toString().equals(material.getVerify_status()))
//			return;
		// 审核失败后未上传
		if (FrameStatus.InActive.toString().equals(material.getReupload_status())) {
			return;
		}

		// 不是身份证直接返回
		if (!StdCertType.IdCard.equals(std.getCert_type()))
			return;
//		// 判断状态
//		if (!StdRegStatus.Complete.equals(std.getReg_status())) {
//			// 未完成注册，判断是否需要验证
//			if (!FrameStatus.Active.toString().equals(CollectionHelper.getParamValue(AppHelper.GobalParamMap,
//					ArtParamName.EnrolVerifyStdIdentity, "InActive"))) {
//				return;
//			}
//
//		}
		// 判断次数
		StdRes res = daoRes.findRes(std_id, StdResType.NoCrownPhoto.toString());

		String max = CollectionHelper.getParamValue(ArtParamHelper.GobalParamMap, "EnrolNoCrownPhotoNumber", "5");

		if (optr == null) {
			if (res != null && res.getRes_number() != null && res.getRes_date() != null
					&& res.getRes_date().isEqual(LocalDate.now()) && res.getRes_number() >= Integer.parseInt(max))
				throw new BusinessException("该考生免冠证件照公安验证接口本日已超限，请明日再试！");
		}
		if (res == null) {
			res = new StdRes();
			res.setStd_id(std.getStd_id());
//			res.setWeixin_id(std.getWeixin_id());
			res.setRes_type(StdResType.NoCrownPhoto.toString());
		}

		if (optr == null)
			optr = new FrameOptr();
		optr.setOptr_id(0);
		optr.setOptr_name("admin");
		IdentifiedResult result = IdentityAI.instance().verify(file, std.getCert_id(), std.getStd_name());

		StdResLog log = new StdResLog();
		log.setRes_type(StdResType.NoCrownPhoto.toString());
//		log.setWeixin_id(std.getWeixin_id());
		log.setStd_id(std.getStd_id());
		log.setRes_param(file.getName() + (result.isSuccess() ? "" : ("->" + result.getError_msg())));
		log.setRes_result(result.getPercent() + "");
		daoRes.logRes(log);

		// 验证完成，记录验证参数
		if (res.getRes_date() == null || !res.getRes_date().isEqual(LocalDate.now())) {
			res.setRes_date(LocalDate.now());
			res.setRes_number(1);
		} else {
			res.setRes_number(res.getRes_number() == null ? 1 : (res.getRes_number() + 1));
		}
		// res.setRes_number(5);
		daoRes.updateRecord(res);
		if (result.getPercent() < Double.parseDouble(ArtParamHelper.getParamValue(
				ArtParamName.EnrolVerifyStdIdentityPercent, "" + ArtDefaultValue.EnrolIdentifyVerifyPercent))) {
			String msg = "公安认证比对失败：请上传考生本人证件照！";
			if (result.isSuccess() == false)
				msg = result.getError_msg();
			if (ArtParamHelper.SchoolCode.equals("10047")) {
				msg = "身份信息验证未通过，请重新上传个人免冠照";
			}
			this.refuse(material, msg, msg_flag, optr);

		} else {
			this.accept(material, msg_flag, optr);
		}

	}

	public void refuse(StdMaterial material, String refuse_msg, String msg_flag, FrameOptr optr) {
		FrameAssertUtil.isNotEmpty(refuse_msg, "材料审核失败原因不能为空！");
		StdReg std = this.daoStd.find(material.getStd_id());
		this.daoMaterial.refuseMaterial(material.getMaterial_id(), refuse_msg, optr.getOptr_id());
		if (FrameStatus.Active.toString().equals(msg_flag)) {
			// 需要发送消息
			Map<String, Object> map = new HashMap<String, Object>();
			CfEnrolMaterial cf = this.daoLog.find(CfEnrolMaterial.class, "material_type", material.getMaterial_type());
			map.putAll(BeanHelper.toStringMap(cf, true));
			map.putAll(BeanHelper.toStringMap(material, true));
			map.put("VerifyMsg", refuse_msg);
//			ArtWeixinHelper.SendWeiXinTemplate(GobalBusinessType.RefuseMaterial, this.daoStd.find(material.getStd_id()),
//					map);
		}
//		if (material.getMaterial_type().equals(StdMaterialType.NoCrownPhoto)) {
//			this.daoStd.refuseIdentity(std);
//		}

		this.daoLog.log(material.getStd_id(), StdLogType.RefuseMaterial, LocalDateTime.now(), optr,
				material.getMaterial_type(), refuse_msg, msg_flag);

	}

	public void accept(StdMaterial material, String msg_flag, FrameOptr optr) {
		FrameAssertUtil.isNotNull(material);
		this.daoMaterial.acceptMaterial(material.getMaterial_id(), optr.getOptr_id());
		if (FrameStatus.Active.toString().equals(msg_flag)
				&& StdMaterialType.NoCrownPhoto.equals(material.getMaterial_type())) {
			// 需要发送消息
			Map<String, Object> map = new HashMap<String, Object>();
			CfEnrolMaterial cf = this.daoLog.find(CfEnrolMaterial.class, "material_type", material.getMaterial_type());
			map.putAll(BeanHelper.toStringMap(cf, true));
			map.putAll(BeanHelper.toStringMap(material, true));
//			ArtWeixinHelper.SendWeiXinTemplate(GobalBusinessType.NoCrownValid, this.daoStd.find(material.getStd_id()),
//					map);
		}
//		this.daoStd.verifyStdIdentity(material.getStd_id());
		this.daoLog.log(material.getStd_id(), StdLogType.AcceptMaterial, LocalDateTime.now(), optr,
				material.getMaterial_type());

	}

	public void acceptAll(Integer[] material_ids, FrameOptr optr) {
		if (material_ids == null || material_ids.length == 0)
			return;
		for (int material_id : material_ids) {
			this.daoMaterial.acceptMaterial(material_id, optr.getOptr_id());
			StdMaterial m = this.daoMaterial.find(material_id);
			if (StdMaterialType.NoCrownPhoto.equals(m.getMaterial_type())) {
				// 需要发送消息
				Map<String, Object> map = new HashMap<String, Object>();
				CfEnrolMaterial cf = this.daoLog.find(CfEnrolMaterial.class, "material_type", m.getMaterial_type());
				map.putAll(BeanHelper.toStringMap(cf, true));
				map.putAll(BeanHelper.toStringMap(m, true));
//				ArtWeixinHelper.SendWeiXinTemplate(GobalBusinessType.NoCrownValid, this.daoStd.find(m.getStd_id()),
//						map);
			}
			//this.daoStd.verifyStdIdentity(material.getStd_id());
			this.daoLog.log(m.getStd_id(), StdLogType.AcceptMaterial, LocalDateTime.now(), optr,
					m.getMaterial_type());
		}
	}
	
	/**
	 * 添加照片材料信息
	 * @param stdMaterial
	 * @throws BusinessException
	 */
	public void create(StdMaterial stdMaterial) throws BusinessException {
		FrameAssertUtil.checkParam(stdMaterial.getStd_id(), stdMaterial.getMaterial_type(), stdMaterial.getMaterial_file(),stdMaterial.getFile_type());
		stdMaterial.setFile_type(stdMaterial.getFile_type().trim().toUpperCase());
		stdMaterial.setUpload_time(LocalDateTime.now());
		StdMaterial sm = this.daoMaterial.findMaterial(stdMaterial.getStd_id(), stdMaterial.getMaterial_type());
		if (sm != null) {
			throw new BusinessException("照片已存在，请检查");
		}
		try {
			this.daoMaterial.insert(stdMaterial);
			this.daoLog.log( stdMaterial.getStd_id(), StdLogType.Confirm, LocalDateTime.now(), 
					null, JsonHelper.fromObject(stdMaterial));
		} catch(Exception e) {
			e.printStackTrace();
			throw new BusinessException(e.getMessage());
		}
		
	}
}
