package com.wechat.service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

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

import com.wechat.model.dto.*;
import com.wechat.model.requestDto.KeyWordReq;
import com.wechat.model.responseDto.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Maps;
import com.wechat.common.CommonEnum;
import com.wechat.common.CommonHelper;
import com.wechat.common.Constants;
import com.wechat.common.utils.BaseUtils;
import com.wechat.common.utils.DateUtils;
import com.wechat.common.utils.LocalFileUtil;
import com.wechat.common.utils.MailUtil;
import com.wechat.common.utils.StringsUtils;
import com.wechat.common.utils.WordUtils;
import com.wechat.dao.HotelUserRecievedCVRedisDao;
import com.wechat.dao.JobUvRedisDao;
import com.wechat.dao.MdeHotelCompanyDao;
import com.wechat.dao.MdeJobAdvertisedDao;
import com.wechat.dao.MdeJobFairDao;
import com.wechat.dao.MdeJobInvitationRelDao;
import com.wechat.dao.MdePositionAnotherNameDao;
import com.wechat.dao.MdePositionCvRelDao;
import com.wechat.dao.MdePositionDao;
import com.wechat.dao.MdeUserCvDao;
import com.wechat.dao.MdeUserDao;
import com.wechat.dao.JobPvRedisDao;
import com.wechat.global.CustomException;
import com.wechat.global.base.BaseService;
import com.wechat.global.base.dao.Pagination;
import com.wechat.global.base.dao.PagingResult;
import com.wechat.global.base.dao.RedisWithExpiryTimeDao;
import com.wechat.global.message.InfoMsg;
import com.wechat.model.dbEntity.MdeEducationExperience;
import com.wechat.model.dbEntity.MdeJobAdvertised;
import com.wechat.model.dbEntity.MdeJobInvitationRel;
import com.wechat.model.dbEntity.MdePositionAnotherName;
import com.wechat.model.dbEntity.MdePositionCvRel;
import com.wechat.model.dbEntity.MdeUser;
import com.wechat.model.dbEntity.MdeUserCv;
import com.wechat.model.requestDto.JobCollectionReq;
import com.wechat.model.requestDto.PageReq;
import com.wechat.model.requestDto.PositionSearchReq;

/**
 * 职位service类 职位发布者为 企业用户 职位即为发布的招聘信息
 * 
 * @author tangwc
 *
 */
@Service
public class PositionService extends BaseService{

	@Value("#{configProperties['job.similarJobs.limitSize']}")
	private int similarPositionLimitSize;

	@Value("#{configProperties['job.hotelOtherPosition.limitSize']}")
	private int hotelOtherPositionLimitSize;

	@Value("#{configProperties['upload.base.path']}")
	private String basePackagePath;

	@Value("#{configProperties['upload.path.image']}")
	private String imagePath;

	@Value("#{configProperties['upload.path.file']}")
	private String filePath;

	@Value("#{configProperties['upload.path.template']}")
	private String fileTemplate;

	@Value("#{configProperties['position_five_day_whin']}")
	private Integer fiveDay;
	
	@Value("#{configProperties['upload.base.path']}")
	private String uploadBasePath;


	@Autowired
	private MdeJobInvitationRelDao mdeJobInvitationRelDao;

	@Resource
	private CommonService commonService;

	@Resource
	private CommonHelper commonHelper;
	
	@Resource
	private MdeJobAdvertisedDao jobAdvertisedDao;

	@Resource
	private MdeUserDao userDao;

	@Resource
	private MdeWorkExperienceService workExperienceService;
	@Resource
	private MdeEducationExperienceService educationExperienceService;

	@Resource
	private MdePositionCvRelDao positionCvDao;

	@Resource
	private MdeHotelCompanyDao hotelCompanyDao;

	@Resource
	private RedisWithExpiryTimeDao redisDao;

	@Resource
	private HotelUserRecievedCVRedisDao hotelUserRecievedCVRedisDao;

	@Resource
	private MdePositionAnotherNameDao positionAnotherName;

	@Autowired
	private MdeUserCvDao userCvDao;
	
	@Autowired
	private MdeJobFairDao jobFairDao;
	
	@Autowired
	private JobUvRedisDao jobUvRedis;
	
	@Autowired
	private JobPvRedisDao pvRedis;
	
	@Autowired
	private MdePositionDao mdePositionDao;
	

	/**
	 * 职位初始化
	 * 
	 * @param userCode
	 * @param lang
	 * @return
	 */
	public Map<String, Object> init(String userCode, String lang) {
		Map<String, Object> map = new HashMap<String, Object>();
		// 头像
		map.put("headPicUrl", commonService.getAdImages(Constants.PC_POSITION_TOP_AD));
		// 推荐酒店列表
		map.put("recommentHotels", commonService.getRecommentHotels());
		// 优选职位推荐 [词典]
		map.put("superiorJobs", commonService.getRecommentJobs());
		return map;
	}
	
	/**
	 * 创建新线程用于异步调用
	 *
	 * @return
	 */
	private ExecutorService cachedThreadPool = Executors.newCachedThreadPool() ;

	/**
	 * 获取企业邀请数量
	 * 
	 * @param userCode
	 * @return
	 */
	public Integer getRecievedHotelInvationInfoCounts(String userCode) {
		return commonService.getRecievedHotelInvationInfoCounts(userCode);
	}

	/**
	 * 职位检索
	 * 
	 * @param searchReq
	 *            keyWord-关键词 position-职位列表 List<Integer>
	 * @param lang
	 * @return
	 */
	@Deprecated
	public PagingResult<JobAdvertisedListDto> searchPositionByKeyWord(PositionSearchReq searchReq, String lang) {
		Pagination page = new Pagination(searchReq.getIndex(), searchReq.getSize());
		Map<Object, Object> pageParam = new HashMap<Object, Object>();
		Set<String> keyWord = getKeywords(searchReq.getKeyWord());
		if (keyWord != null && keyWord.size() > 0)
			pageParam.put("keyWord", keyWord);
		pageParam.put("lang", lang);
		page.setParams(pageParam);
		if(!StringsUtils.isEmpty(searchReq.getSort()))
		{
			switch(searchReq.getSort())
			{
				case Constants.SORT_TIME:
					page.setOrderColumn("a.update_date desc ");
					break;
				case Constants.SORT_GRADE_ASC:
					page.setOrderColumn("pos.POSITION_GRADE asc, a.update_date desc ");
					break;
				case Constants.SORT_GRADE_DESC:
					page.setOrderColumn("pos.POSITION_GRADE desc, a.update_date desc ");
					break;
			}
		}
		PagingResult<JobAdvertisedListDto> rest = jobAdvertisedDao.searchJob(page);
		//加上当日缓存中的pv
		addJobPvTd(rest.getResultList());
		return rest;
	}

	/**
	 * @description 职位关键词搜索（用户版）
	 * @author rayson
	 * @param keyWordReq 关键词
	 * @param req
	 * @date 2023-09-13 14:22
	 * @return PagingResult<JobAdvertisedListDto>
	 **/
	public PagingResult<JobAdvertisedListDto> searchPositionByKeyWord(KeyWordReq keyWordReq, HttpServletRequest req) {
		if (keyWordReq != null && StringsUtils.isEmpty(keyWordReq.getKeyWord())) {
			PagingResult<JobAdvertisedListDto> pagingResult = new PagingResult<>();
			pagingResult.setCurrentPage(keyWordReq.getIndex());
			pagingResult.setTotalSize(0);
			pagingResult.setPageSize(keyWordReq.getSize());
			pagingResult.setResultList(new ArrayList<JobAdvertisedListDto>());
			pagingResult.setPageNoSize(10);
			return pagingResult;
		}
		String language = commonService.getLanguage(req);

		Pagination page = new Pagination(keyWordReq.getIndex(), keyWordReq.getSize());

		Map<Object, Object> pageParam = Maps.newHashMap();
		pageParam.put("lang", language);
		pageParam.put("keyWord", keyWordReq.getKeyWord());
		page.setParams(pageParam);

		PagingResult<JobAdvertisedListDto> rest = jobAdvertisedDao.searchPositionByKeyWord(page);
		//加上当日缓存中的pv
		addJobPvTd(rest.getResultList());
		return rest;
	}
	/**
	 * 职位检索
	 * 
	 * @param searchReq
	 *            keyWord-关键词 position-职位列表 List<Integer>
	 * @param lang
	 * @return
	 */
	public PagingResult<JobAdvertisedListDto> searchPositionByCondition(PositionSearchReq searchReq, String lang) {
		Pagination page = new Pagination(searchReq.getIndex(), searchReq.getSize());
		Map<Object, Object> pageParam = new HashMap<Object, Object>();

		if (searchReq.getPosition() != null && searchReq.getPosition().size() > 0) {
			pageParam.put("position", searchReq.getPosition());
		}
		if (!StringsUtils.isEmpty(searchReq.getAddCity()))
			pageParam.put("addCity", searchReq.getAddCity());
		if (!StringsUtils.isEmpty(searchReq.getAddArea()))
			pageParam.put("addArea", searchReq.getAddArea());
		if (!StringsUtils.isEmpty(searchReq.getAddProvince()))
			pageParam.put("addProvince", searchReq.getAddProvince());
		
		//酒店筹开类型
		if (!StringsUtils.isEmpty(searchReq.getPrepareFlag())) {
			pageParam.put("prepareFlag", searchReq.getPrepareFlag());
		}

		//职位发布时间
		if (!StringsUtils.isEmpty(searchReq.getPositionPubTime())) {
			LocalDate fromDate = LocalDate.now();
			switch(CommonEnum.POSITION_PUB_TIME.getByValue(searchReq.getPositionPubTime())){
				case WEEK:
					fromDate = fromDate.minusDays(7);
					break;
				case MONTH:
					fromDate = fromDate.minusMonths(1);
					break;
				case MONTHS:
					fromDate = fromDate.minusMonths(3);
					break;
				case YEAR:
					fromDate = fromDate.minusMonths(6);
					break;
				default:
					fromDate = fromDate.minusDays(7);
					break;
			}
			pageParam.put("fromDate", DateUtils.localDateformatString(fromDate, DateUtils.PATTEN_YMD));
		}
		
		pageParam.put("lang", lang);
		page.setParams(pageParam);
		//自定义排序
		if(!StringsUtils.isEmpty(searchReq.getSort()))
		{
			switch(searchReq.getSort())
			{
				case Constants.SORT_TIME:
					page.setOrderColumn("a.update_date desc ");
					break;
				case Constants.SORT_GRADE_ASC:
					page.setOrderColumn("pos.POSITION_GRADE asc, a.update_date desc ");
					break;
				case Constants.SORT_GRADE_DESC:
					page.setOrderColumn("pos.POSITION_GRADE desc, a.update_date desc ");
					break;
			}
		}
		PagingResult<JobAdvertisedListDto> rest = jobAdvertisedDao.searchJob(page);
		//加上当日缓存中的pv
		addJobPvTd(rest.getResultList());
		return rest;
	}

	@Autowired
	protected RedisTemplate<String, List<MdePositionAnotherName>> redisTemplate;

	// 将输入的关键字作拆分成
	public Set<String> getKeywords(String key) {
		if (StringsUtils.isEmpty(key)) {
			return null;
		}
		String[] keys = key.trim().split(" ");// 以空格区分关键字
		// String[] keys = calcPartMatch(key.trim()); // 暴力拆分 关键字,
		if (keys.length == 0) {
			return null;
		}
		Set<String> wordSet = new HashSet<String>();
		for (String k : keys) {
			if (!StringsUtils.isEmpty(k)) {
				wordSet.add(k);
			}
		}
		// String testTxt = getLongAliasOfPositionName();
		// return KeyWordUtil.returnKeys(wordSet, testTxt);
		return wordSet;
	}
	
	/**
	 * 优选职位 -分页查询
	 * 
	 * @return
	 */
	public PagingResult<JobAdvertisedListDto> getPagingRecommentJobs(PageReq searchReq,String userCode) {
		Pagination page = new Pagination(searchReq.getIndex(), searchReq.getSize());
		Map<Object, Object> pageParam = new HashMap<Object, Object>();
		pageParam.put("userCode", userCode);
		//查询8个月内的职位
		pageParam.put("selDate", DateUtils.localDateformatString(LocalDate.now().minusMonths(8), DateUtils.PATTEN_YMD));
		page.setParams(pageParam);
		
		return jobAdvertisedDao.getPagingRecommentJobs(page);
	}

	/**
	 * 计算部分匹配值
	 */
	public String[] calcPartMatch(String keyword) {
		Set<String> set = new HashSet<String>();
		for (int i = 0; i < keyword.length(); i++) {
			if (i == 0)
				continue;
			String subKey = keyword.substring(0, i + 1);
			// 求前缀
			for (int j = 1; j < subKey.length(); j++) {
				set.add(subKey.substring(0, j));
			}
			// 求后缀
			for (int j = 1; j < subKey.length(); j++) {
				set.add(subKey.substring(j, subKey.length()));
			}
		}
		// 删除一个长度为1的元素
		Iterator<String> it = set.iterator();
		while (it.hasNext()) {
			String x = it.next();
			if (x.length() == 1)
				it.remove();
		}
		String[] aa = new String[set.size()];
		set.toArray(aa);// list转String数组
		return aa;

	}

	public String getLongAliasOfPositionName() {
		StringBuilder builder = new StringBuilder();
		List<MdePositionAnotherName> list = redisTemplate.opsForValue().get("positionNameAnotherList");
		if (list == null || list.size() == 0) {
			list = positionAnotherName.getAllAliasNameOfPosition();
			redisTemplate.opsForValue().set("positionNameAnotherList", list);
		}
		for (MdePositionAnotherName name : list) {
			builder.append(name.getPositionName());
		}
		return builder.toString();
	}

	/**
	 * 职位详情 > 企业信息，职位信息，相似职位列表，该酒店其他职位列表，底部广告
	 * 
	 * @param userCode
	 * 
	 * @param positionId
	 * @return
	 */
	public Map<String, Object> getPositionDetail(int jobId, String userCode,String lang, String inShareJob) {
		//结果封装用
		Map<String, Object> map = new HashMap<String, Object>();
		//各类相关信息获取
		// 职位信息
		MdeJobAdvertised jobAdvertised = jobAdvertisedDao.getInfoById(jobId,lang);
		//分享用职位id
		String shareJob = BaseUtils.getShareJob(jobAdvertised.getCreateDate(),jobId);
		
		// 获取企业信息
		MdeUser userInfo = userDao.getHotelUserInfoByJobId(jobId);
		//将user和返回类中相同属性复制至返回集中
		BaseEnterpriseUserResp hotelInfo = new BaseEnterpriseUserResp();
		BeanUtils.copyProperties(userInfo, hotelInfo);
		//敏感数据处理
		if("0".equals(userInfo.getIdentityFlag()))
		{
			//个人用户去除手机号
			hotelInfo.setUserName(null);
		}
		//去除用户code
		hotelInfo.setUserCode(null);

		//非登录状态下
		if(!StringsUtils.isEmpty(inShareJob))
		{
			if(!shareJob.equals(inShareJob))
			{
				//验证分享用的jobid，职位id不正确情况下
				return null;
			}

			// 返回加密后的用户id
			jobAdvertised.setPublisher(commonHelper.getShareCodeAes(userInfo.getUserCode(), userInfo.getCreateDate()));	
			//去除账号信息
			hotelInfo.setUserName(null);
		}
		//企业信息实装
		map.put("hotelInfo", hotelInfo);
		
		// 相似职位列表
		List<JobAdvertisedListDto> similarPositionList = jobAdvertisedDao.getSimilarJobs(jobId, similarPositionLimitSize);
		//加上当日缓存中的pv
		addJobPvTd(similarPositionList);

		// 该酒店其他职位列表
		List<MdeJobAdvertised> hotelOtherPositionList = jobAdvertisedDao.gethotelOtherPositionList(jobId, jobAdvertised.getPublisher(),hotelOtherPositionLimitSize);
		
		//登陆状态
		if(StringsUtils.isEmpty(inShareJob))
		{
			//酒店(职位)邀请信息状态修改
			try {
				ArrayList<String> invationInfo = commonService.getRecievedHotelInvationInfo(userCode);
				if (invationInfo.contains(String.valueOf(jobId))) {
					Map<String, Object> params = Maps.newHashMap();
					params.put("jobId", jobId);
					params.put("userCode", userCode);
					params.put("status", 1); // 1已读
					mdeJobInvitationRelDao.updateStatus(params);
					// 从redis中清除该职位Id
					invationInfo.remove(String.valueOf(jobId));
					// 更新redis
					commonService.updateUserInvatedCvCount(userCode, invationInfo);
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw new CustomException(InfoMsg.ERROR_UPDATE_USERCVSTATUS_FILE);
			}
			
			// 查看该用户是否被邀请过
			Map<String,Object> maps = Maps.newHashMap();
			maps.put("userCode", userCode);
			maps.put("jobId", jobId);
			MdeJobInvitationRel mdeJobInvitationRel = mdeJobInvitationRelDao.passiveInvitation(maps);
			Calendar cal = Calendar.getInstance();
			cal.setTime(new Date());
			cal.add(Calendar.DAY_OF_MONTH, -fiveDay);
			// 是否投递过该职位 （五天之内不可投递同一职位）
			MdePositionCvRel posCv = positionCvDao.hasPosted(userCode, jobId, cal.getTime());
			boolean flag = false;
			if (mdeJobInvitationRel != null && mdeJobInvitationRel.getStatus().equals("2")) {
				flag=true;
			} else if(mdeJobInvitationRel != null && posCv != null) {
				flag =false;
			} else if (posCv != null){
				flag= true;
			}
			map.put("hasPosted", flag);
		}else {
			//非登陆状态不传递主key
			jobAdvertised.setJobId(null);
		}

		// 返回结果实装
		// 分享用职位id
		map.put("shareJob", shareJob);
		// 职位信息
		jobAdvertised.setCreateDate(null);
		map.put("positionInfo", jobAdvertised);
		// 相似职位列表
		map.put("similarPositionList", commonService.makeJobAdvertisedImg2(similarPositionList,inShareJob));

		// 该酒店其他职位列表
		map.put("hotelOtherPositionList", commonService.makeJobAdvertisedImg(hotelOtherPositionList,inShareJob));
		// 底部广告
		map.put("advertisement", commonService.getAdImages(Constants.PC_POSITION_DETAIL_BOTTOM_AD));
		
		return map;
	}

	/**
	 * 职位收藏与取消
	 * 
	 * @param collection
	 * @return
	 */
	@Transactional
	public int updateUserJobCollection(JobCollectionReq collection) {
		return userDao.updateUserPositionList(collection);
	}

	/**
	 * 用户简历投递
	 * 
	 * @param collection
	 *            => userCode jobId
	 * @return
	 */
	@Transactional
	public int postCurriculumVitae(JobCollectionReq collection, HttpServletRequest req) {
		String userCode = commonService.getUserCode(req);
		MdeUserCv mdeUserCv = null;
		if (collection.getCvId() != null) {
			mdeUserCv = userCvDao.getInfoById(collection.getCvId(),userCode);
		}
		// 获取个人用户信息
		MdeUser mdeUser = userDao.getUserInfoByCode(userCode);
		if (mdeUser != null && mdeUser.getIdentityFlag().equals("1")) {
			throw new CustomException(InfoMsg.EERROE_ENTERPRISEADVER_ERROR);
		}
		// 通过职位获取企业信息
		MdeUser hotelUser = userDao.getHotelUserInfoByJobId(collection.getJobId());
		if (hotelUser == null) {
			throw new CustomException(InfoMsg.ERROR_HOTEL_NOTEXSIT);// 酒店不存在
		}
		
		Map<String, Object> maps = Maps.newHashMap();
		maps.put("userCode", userCode);
		maps.put("jobId", collection.getJobId());
		// 查看该用户是否被邀请过
		MdeJobInvitationRel mdeJobInvitationRel = mdeJobInvitationRelDao.passiveInvitation(maps);
		// 组织投递信息
		Date d = new Date();
		// 投递信息入库
		MdePositionCvRel cv = new MdePositionCvRel();
		cv.setPosId(collection.getJobId());
		cv.setCandidate(userCode);
		cv.setDeliverDate(d);
		cv.setDelFlag(0);
		cv.setMatchingDegree(0.0);
		cv.setRemarks("");
		cv.setCvStatus("0");
		cv.setVersionNo(1);
		cv.setCreateDate(d);
		cv.setCreateBy(userCode);
		cv.setUpdateDate(d);
		cv.setUpdateBy(userCode);
		cv.setCvTitle(StringsUtils.nvl(collection.getCvTitle()));
		//发布者
		cv.setPublisher(hotelUser.getUserCode());
		
		if (mdeUserCv != null && StringsUtils.isNotEmpty(mdeUserCv.getCvUrl())) {
			cv.setCvUrl(mdeUserCv.getCvUrl());
		} else {
			cv.setCvUrl("");
		}
		// 查询是否投递过该职位
		MdePositionCvRel cvFromDB = positionCvDao.getInfoByIdAndUserCode(cv);
		int i = 0;
		// 被动投递 (被邀请的)
		if (mdeJobInvitationRel != null) {
			if (mdeJobInvitationRel.getStatus().equals("2")) {
				throw new CustomException(InfoMsg.REPEAT_POST_POSITION);
			}
			maps.put("status", 2); // 已投递
			mdeJobInvitationRelDao.updateStatus(maps); // 更新邀请关系表 （已投递）
			if (cvFromDB != null) {
				// 组织参数
				cvFromDB.setPosId(collection.getJobId());
				cvFromDB.setCandidate(userCode);
				cvFromDB.setDeliverDate(d);
				cvFromDB.setCvStatus("0");
				cvFromDB.setCreateDate(d);
				cvFromDB.setCreateBy(userCode);
				cvFromDB.setUpdateDate(d);
				cvFromDB.setUpdateBy(userCode);
				cvFromDB.setCvTitle(StringsUtils.nvl(collection.getCvTitle()));
				if (mdeUserCv != null && StringsUtils.isNotEmpty(mdeUserCv.getCvUrl())) {
					cvFromDB.setCvUrl(mdeUserCv.getCvUrl());
				} else {
					cvFromDB.setCvUrl("");
				}
				i = positionCvDao.updatePositionCvRel(cvFromDB); // 更新投递履历记录
			} else {
				i = positionCvDao.insertUserCvRel(cv); // 新增投递
			}
			// 清除企业邀请的职位id （收到企业邀请的职位Id）
			ArrayList<String> invationInfo = commonService.getRecievedHotelInvationInfo(userCode);
			invationInfo.remove(collection.getJobId().toString());
			// 更新redis (单个清除)
			commonService.updateUserInvatedCvCount(userCode, invationInfo);
		} else {
			// 主动投递
			if (cvFromDB != null) {
				Calendar cal = Calendar.getInstance();
				cal.setTime(d);
				cal.add(Calendar.DATE, -fiveDay);// 向前退五天 即 五天之内不允许再次投递同一职位
				if (cvFromDB.getDeliverDate().after(cal.getTime())) {
					throw new CustomException(InfoMsg.REPEAT_POST_POSITION);
				}
				// 组织参数
				cvFromDB.setPosId(collection.getJobId());
				cvFromDB.setCandidate(userCode);
				cvFromDB.setDeliverDate(d);
				cvFromDB.setCvStatus("0");
				cvFromDB.setCreateDate(d);
				cvFromDB.setCreateBy(userCode);
				cvFromDB.setUpdateDate(d);
				cvFromDB.setUpdateBy(userCode);
				cvFromDB.setCvTitle(StringsUtils.nvl(collection.getCvTitle()));
				if (mdeUserCv != null && StringsUtils.isNotEmpty(mdeUserCv.getCvUrl())) {
					cvFromDB.setCvUrl(mdeUserCv.getCvUrl());
				} else {
					cvFromDB.setCvUrl("");
				}
				i = positionCvDao.updatePositionCvRel(cvFromDB); // 更新投递履历记录
			} else {
				i = positionCvDao.insertUserCvRel(cv); // // 新增投递
			}
		}
		collection.setUserHeadPortrait(commonService.addDomainAndTs(mdeUser.getHeadPortrait()));
		collection.setUserName(mdeUser.getName());
		// 投递信息存入redis
		commonService.insertHotelUserRecievedCv(hotelUser.getUserCode(), collection);
		// 获取职位信息
//		MdeJobAdvertisedEntity mdeJobInfo = jobAdvertisedDao.getJobAdvertisedById(collection.getJobId());
		//发送新简历提醒给企业
		/*sendEmailInfo(hotelUser,mdeJobInfo);*/
		return i;
	}
	

	
	/**
	 * 发送新简历提醒给企业(异步)
	 * 
	 * @param list
	 * @return
	 */
/*	public void sendEmailInfo(final MdeUser hotelUser, final MdeJobAdvertisedEntity mdeJobInfo) {
		// 新线程，异步操作
		cachedThreadPool.submit(new Runnable() {
			@Override
			public void run() {
				try {
					// 发送邮件模板
					InputStream in = this.getClass().getClassLoader()
							.getResourceAsStream("template/mdeNewCvEmail_cn.html");
					byte[] bytes = new byte[in.available()];
					in.read(bytes);
					String htmlStr = new String(bytes);
					htmlStr = htmlStr.replace("{0}", mdeJobInfo.getJobName());// 职位名称
					String mailContent = htmlStr;
					if (!mailUtil.sendMailNew(hotelUser.getUserName(), mailContent, "新简历投递通知")) {
						log.error("新简历投递通知发送失败：[" + hotelUser.getName() + hotelUser.getUserName() + "]");
					}

				} catch (Exception e) {
					log.error("新简历投递通知，邮件发送异常", e);
					throw new CustomException(InfoMsg.ERROR_SEND_EMAIL_FAIL);
				}
			}
		});
	}*/

//	/**
//	 * 批量更新jia
//	 * 
//	 * @param list
//	 * @return
//	 */
//	public int updateCvState(List<String> list) {
//		return 0;
//	}

	/**
	 * 下载用户简历 需要参数userCode 从公共方法中获取 controller 返回值为 void
	 * 
	 * @param request
	 * @param response
	 */
	public String exportUserCvDoc(HttpServletResponse response, String userCode,String lang) {
		Map<String, Object> map = new HashMap<String, Object>();
		MdeUser user = userDao.exportUserCvDoc(userCode);
		map.put("name", strValue(user.getName()));
		map.put("userName", strValue(user.getUserName()));
		map.put("experience", strValue((int) user.getExperience() + ""));
		map.put("address", strValue(user.getAddress()));
		map.put("birthday", strValue(user.getBirthday()));
		map.put("email", strValue(user.getEmail()));
		// 获取用户工作
		List<WorkExperienceBaseDto> workList = workExperienceService.getBaseWorkExperienceByUserCode(userCode);
		for (int i = 0; i < 3; i++) {
			try {
				WorkExperienceBaseDto work = workList.get(i);
				map.put("wstart" + i, dateFormat(work.getEnterDate(), ".", true));
				map.put("wend" + i, work.getQuitDate() == null ? "- 至今" : dateFormat(work.getQuitDate(), ".", false));
				map.put("coName" + i, strValue(work.getCoName()));
				map.put("positionTitle" + i, strValue(work.getPositionTitle()));
			} catch (Exception e) {
				map.put("wstart" + i, " ");
				map.put("wend" + i, " ");
				map.put("coName" + i, " ");
				map.put("positionTitle" + i, " ");
			}
		}
		// 获取用户教育履历
		List<MdeEducationExperience> educationList = educationExperienceService
				.getEducationExperienceByUserCode(userCode,lang);
		for (int i = 0; i < 2; i++) {
			try {
				MdeEducationExperience education = educationList.get(i);
				if (i == 0) {
					map.put("schName", strValue(education.getSchName()));
					map.put("education", education.getEducationName());
				}
				map.put("estart" + i, dateFormat(education.getEnterDate(), ".", true));
				map.put("eend" + i, dateFormat(education.getQuitDate(), ".", false));
				map.put("schName" + i, strValue(education.getSchName()));
				map.put("speciality" + i, "专业：" + strValue(education.getSpeciality()));
				map.put("education" + i, strValue(education.getEducationName()));
			} catch (Exception e) {
				if (i == 0) {
					map.put("schName", " ");
					map.put("education", " ");
				}
				map.put("estart" + i, " ");
				map.put("eend" + i, " ");
				map.put("schName" + i, " ");
				map.put("speciality" + i, " ");
				map.put("education" + i, " ");
			}
		}
		StringBuffer buffer = new StringBuffer();
		buffer.append(user.getName() + "(");
		buffer.append(user.getUserName() + ")_门墩儿.docx");
		return WordUtils.poiTlWord(response, map, basePackagePath, fileTemplate, buffer.toString());
	}

	public String strValue(String str) {
		return StringsUtils.isEmpty(str) ? " " : str;
	}

	public String dateFormat(Date d, String pattern, boolean flag) {
		if (d == null)
			return " ";
		if (flag) {
			return new SimpleDateFormat("yyyy" + pattern + "MM").format(d);
		} else {
			return "- " + new SimpleDateFormat("yyyy" + pattern + "MM").format(d);
		}

	}
	
	
	/**
	 * 获取招聘会参会酒店信息
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public JobFairByHotelResp getJobFairByHotel(Integer fairId) throws UnsupportedEncodingException {
		
		JobFairByHotelResp fairInfo = jobFairDao.getJobFairByHotel(fairId);
		if(null != fairInfo) {
			String shareImg = fairInfo.getShareImg();
			if(!StringsUtils.isEmpty(shareImg)) {
				shareImg = uploadBasePath+URLDecoder.decode(shareImg, "utf-8");
				shareImg = LocalFileUtil.getImgBase64Str(shareImg);
				fairInfo.setShareImg(shareImg);
			}
		}
		
		return fairInfo;
	}
	
	/**
	 * 获取招聘会参会酒店 城市信息
	 * @return
	 */
	public List<City> getJobFairCitys(Integer fairId) {
		
		return jobFairDao.getJobFairCitys(fairId);
	}

	
	/**
	 * 获取招聘会参会酒店 职位信息
	 * @return
	 */
	public List<DPResp> getJobFairDepartments(Integer fairId) {
		
		return jobFairDao.getJobFairDepartments(fairId);
	}

	
	/**
	 * 职位详情Pv Uv统计
	 * 
	 * @param list
	 * @return
	 */
	public void recodeJobDtlPvUv(Integer jobId, HttpServletRequest request) {
		try {
			//记录pv
			pvRedis.insertJobDtlPv(String.valueOf(jobId));
			//记录uv
			jobUvRedis.insertUv(String.valueOf(jobId), commonHelper.getIRealIPAddr(request));

		} catch (Exception e) {
			log.error("******************************职位详情Pv Uv统计异常******************************", e);
		}
	}
	
	/**
	 * 实时的总PV
	 * 
	 * @param list
	 * @return
	 */
	public void addJobPvTd(List<JobAdvertisedListDto> jobList) {
		try {
			for(JobAdvertisedListDto jobDto : jobList)
			{
				int oldPv = jobDto.getPageView();
				//实时的总PV是 Db中的+缓存中的
				jobDto.setPageView(oldPv + pvRedis.getJobPvById(jobDto.getJobId()));;
			}
		} catch (Exception e) {
			log.error("****************************** 实时的总PV 计算异常******************************", e);
		}
	}
	
	/**
	 * 根据jobid获取pv
	 * 
	 * @param list
	 * @return
	 */
	public int getPvByJobId(Integer jobid) {
		int jobPv = mdePositionDao.getPvByJobId(jobid);
		try {
			//实时的总PV是 Db中的+缓存中的
			jobPv = jobPv + pvRedis.getJobPvById(jobid);
		} catch (Exception e) {
			log.error("****************************** 实时的总PV 计算异常******************************", e);
		}
		return jobPv;
	}
	
	
	/**
	 * 根据statisticType获取起止时间
	 * @param statisticType 0：按天 1：按月 2：按年
	 * @return
	 */
	public JobViewDateViewDto getStrEndDataByType(String statisticType, Date dayStartD, Date dayEndD) {
		JobViewDateViewDto dvDto = new JobViewDateViewDto();
		LocalDate nowLd = LocalDate.now();
		
		String dayEndStr = "";
		String dayStartStr = "";

		String ymd = "";
		switch(statisticType)
		{
			case "":
				//查询近15天数据，按天集记
				dayStartStr = DateUtils.localDateYMDString(nowLd.minusDays(15));
				dayEndStr = DateUtils.localDateYMDString(nowLd);
				ymd = "d";
				break;
			case "0":
				if(dayEndD == null || dayStartD == null)
				{
					//查询近15天数据，按天集记
					dayStartStr = DateUtils.localDateYMDString(nowLd.minusDays(15));
					dayEndStr = DateUtils.localDateYMDString(nowLd);
				} else {
					//根据所选时间查询，按天集记
					dayStartStr = DateUtils.formatString(dayStartD, DateUtils.PATTEN_YMD);
					dayEndStr = DateUtils.formatString(dayEndD, DateUtils.PATTEN_YMD);
				}
				ymd = "d";
				break;
			case "1":
				//查询本年数据，按月集记
				if(dayEndD == null || dayStartD == null)
				{
					//查询近1年的数据 从当月第一天开始计算
					dayStartStr = DateUtils.localDateYMDString(DateUtils.getFistDayOfMonth(nowLd.minusYears(1)));
					//结束月的最后一天
					dayEndStr = DateUtils.localDateYMDString(DateUtils.getLastDayOfMonth(nowLd));
				} else {
					//从当月第一天开始计算
					dayStartStr = DateUtils.localDateYMDString(DateUtils.getFistDayOfMonth(dayStartD));
					//结束月的最后一天
					dayEndStr = DateUtils.localDateYMDString(DateUtils.getLastDayOfMonth(dayEndD));
				}
				ymd = "m";
				break;
			case "2":
				//按年集记
				if(dayEndD == null || dayStartD == null)
				{
					//查询近5年的数据 从当年第一天开始计算
					dayStartStr = DateUtils.localDateYMDString(DateUtils.getFistDayOfYear(nowLd.minusYears(5)));
					//结束年的最后一天
					dayEndStr = DateUtils.localDateYMDString(DateUtils.getLastDayOfYear(nowLd));
				} else {
					//从当年第一天开始计算
					dayStartStr = DateUtils.localDateYMDString(DateUtils.getFistDayOfYear(dayStartD));
					//结束年的最后一天
					dayEndStr = DateUtils.localDateYMDString(DateUtils.getLastDayOfYear(dayEndD));
				}
				ymd = "y";
				break;
		}
		dvDto.setDayEndStr(dayEndStr);
		dvDto.setDayStartStr(dayStartStr);
		dvDto.setYmd(ymd);
		return dvDto;
	}
	
	/**
	 * 查询总体的职位点击量，按时间统计
	 * @return
	 */
	public List<JobRepFormPvDto> findRepFormPvByDate(String userCode, JobViewDateViewDto dvDto, Integer jobId) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userCode", userCode);
		map.put("from", dvDto.getDayStartStr());
		map.put("to", dvDto.getDayEndStr());
		map.put("ymd", dvDto.getYmd());
		map.put("jobId", jobId);
		return jobAdvertisedDao.findRepFormPvByDate(map);
	}
	
	/**
	 *查询总的职位点击、投递量，漏斗图
	 * @return
	 */
	public Map<String, Integer> findGeneralViewByDate(String userCode, JobViewDateViewDto dvDto, Integer jobId) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userCode", userCode);
		map.put("from", dvDto.getDayStartStr());
		map.put("to", dvDto.getDayEndStr());
		map.put("ymd", dvDto.getYmd());
		map.put("jobId", jobId);
		
		//使用LinkedHashMap(保留插入时的顺序)
		Map<String, Integer> restMap = new LinkedHashMap<String, Integer>();
		restMap.put("职位访问", jobAdvertisedDao.findGeneralPvByDate(map));
		restMap.put("简历投递", positionCvDao.countCvsByDateStaus(map));
		map.put("cvStatus", "2");
		restMap.put("简历下载", positionCvDao.countCvsByDateStaus(map));
		map.put("cvStatus", "3");
		restMap.put("邀请面试", positionCvDao.countCvsByDateStaus(map));
		
		return restMap;
	}
	
	
	/**
	 *  查询投递简历人员学历情况
	 * @return
	 */
	public List<LVResp>  countEducationByDate(String userCode, JobViewDateViewDto dvDto, Integer jobId) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userCode", userCode);
		map.put("from", dvDto.getDayStartStr());
		map.put("to", dvDto.getDayEndStr());
		map.put("ymd", dvDto.getYmd());
		map.put("jobId", jobId);
		
		return positionCvDao.countEducationByDate(map);
	}
	
	/**
	 *  查询时间段内 各职位投递和阅读量
	 * @return
	 */
	public List<JobRepFormDtlDto>  getReportsFormByDate(String userCode, JobViewDateViewDto dvDto) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("userCode", userCode);
		map.put("from", dvDto.getDayStartStr());
		map.put("to", dvDto.getDayEndStr());
		map.put("ymd", dvDto.getYmd());
		
		return positionCvDao.getReportsFormByDate(map);
	}
}
