package com.pcloud.book.book.biz.impl;

import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookFundBiz;
import com.pcloud.book.book.dao.BookFundDao;
import com.pcloud.book.book.dto.BookFundDto;
import com.pcloud.book.book.dto.BookFundInfoDto;
import com.pcloud.book.book.entity.BookFund;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.page.PageBean;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.string.StringUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @描述：书刊基金业务实现层
 * @作者：lihao
 * @创建时间：2017年7月19日,下午3:14:10 @版本：1.0
 */
@Service("bookFundBiz")
public class BookFundBizImpl implements BookFundBiz {

	private static final Logger LOGGER = LoggerFactory.getLogger(BookFundBizImpl.class);

	@Autowired
	private BookFundDao bookFundDao;

	/**
	 * 创建书刊基金状态
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void create(BookFund bookFund) {
		LOGGER.info("【书刊管理(平台端)】创建书刊基金状态,<START>.[bookFund]:{}" , bookFund);
		// 参数校验
		this.checkAddParam(bookFund);
		// 判断有效期是否重复
		this.timeIsExsit(bookFund);
		try {
			bookFundDao.insert(bookFund);
		} catch (Exception e) {
			LOGGER.error("【书刊管理(平台端)】创建书刊基金状态,<ERROR>.[bookFundDao.insert]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "创建书刊基金状态失败！");
		}
	}

	/**
	 * 修改刊基金状态
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void update(BookFund bookFund) {
		LOGGER.info("【书刊管理(平台端)】修改刊基金状态,<START>.[bookFund]:{}", bookFund);
		if (null == bookFund.getBookFundId()) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "基金标识不能为空！");
		}
		if (null == bookFund.getEndTime()) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "基金结束时间不能为空！");
		}
		BookFundDto bookFundDto = bookFundDao.getByBookFundId(bookFund.getBookFundId());
		if (null == bookFundDto) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "该基金不存在！");
		}
		bookFund.setStartTime(DateUtils.formatDate(bookFundDto.getStartTime()));
		// 判断有效期是否重复
		this.timeIsExsit(bookFund);
		try {
			bookFundDao.update(bookFund);
		} catch (Exception e) {
			LOGGER.error("【书刊管理(平台端)】修改刊基金状态,<ERROR>.[bookFundDao.insert]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "修改刊基金状态失败！");
		}
	}

	/**
	 * 校验参数
	 */
	private void checkAddParam(BookFund bookFund) throws BizException {

		if (null == bookFund.getBookId()) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识码不能为空！");
		}
		if (StringUtil.isEmpty(bookFund.getFundName())) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "基金名称不能为空！");
		}
		if (null == bookFund.getPurchaseMoney()) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "基金购买金额不能为空！");
		}
		if (null == bookFund.getStartTime()) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "基金开始时间不能为空！");
		}
		if (null == bookFund.getEndTime()) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "基金结束时间不能为空！");
		}
		if(StringUtil.isEmpty(bookFund.getContractNo())){
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "挂牌/合同编号不能为空！");
		}
		if(StringUtil.isEmpty(bookFund.getBatchNumber())){
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "批次号不能为空！");
		}
		if(bookFund.getContractNo().length()>30){
			throw new BookBizException(BookBizException.PARAM_IS_ERROR, "挂牌/合同编号长度过长！");
		}
		if(bookFund.getBatchNumber().length()>30){
			throw new BookBizException(BookBizException.PARAM_IS_ERROR, "批次号长度过长！");
		}
	}

	/**
	 * 判断基金购买有效期是否重复
	 */
	private void timeIsExsit(BookFund bookFund) throws BizException {
		Long bookId = bookFund.getBookId();
		List<BookFundDto> bookFundDtos = null;
		if (bookFund.getBookFundId() == null) {// 新增
			bookFundDtos = bookFundDao.getByBookId(bookId);
		} else { // 修改
			Map<String, Object> paramMap = new HashMap<>();
			paramMap.put("bookId", bookId);
			paramMap.put("bookFundId", bookFund.getBookFundId());
			bookFundDtos = bookFundDao.getFundListByMap(paramMap);
		}
		if (null != bookFundDtos && bookFundDtos.size() != 0) {
			Long sTime = DateUtils.StringToDateTime(bookFund.getStartTime()).getTime();// 未加开始时间
			Long eTime = DateUtils.StringToDateTime(bookFund.getEndTime()).getTime();// 未加结束时间
			for (BookFundDto bookFundDto : bookFundDtos) {
				Long startTime = bookFundDto.getStartTime().getTime();// 已加开始时间
				Long endTime = bookFundDto.getEndTime().getTime();// 已加结束时间
				try {
					if (startTime < sTime && sTime < endTime) {// 未加开始时间不在已加有效期之内，否则重复
						throw new BookBizException(BookBizException.PARAM_IS_EXIST, "基金支持有效期已存在！");
					}
					if (startTime < eTime && eTime < endTime) {// 未加结束时间不在已加有效期之内，否则重复
						throw new BookBizException(BookBizException.PARAM_IS_EXIST, "基金支持有效期已存在！");
					}
					if (sTime < startTime && startTime < eTime) {// 已加开始时间不在未加有效期之内，否则重复
						throw new BookBizException(BookBizException.PARAM_IS_EXIST, "基金支持有效期已存在！");
					}
					if (sTime < endTime && endTime < eTime) {// 已加结束时间不在未加有效期之内，否则重复
						throw new BookBizException(BookBizException.PARAM_IS_EXIST, "基金支持有效期已存在！");
					}
					if (sTime.equals(startTime) && eTime.equals(endTime)) {// 已加有效期与未加有效期相同
						throw new BookBizException(BookBizException.PARAM_IS_EXIST, "基金支持有效期已存在！");
					}

				} catch (BookBizException e) {
					throw new BookBizException(BookBizException.PARAM_IS_EXIST,
							bookFundDto.getFundName() + "已经购买了" + DateUtils.getShortDateStr(bookFundDto.getStartTime())
									+ "至" + DateUtils.getShortDateStr(bookFundDto.getEndTime()) + "时间段的收益，不能设置重叠时间");
				}
			}
		}
	}

	/**
	 * 根据BookId获取基金状态
	 */
	@Override
	public List<BookFundDto> getByBookId(Long bookId) {
		LOGGER.info("【书刊管理(平台端)】根据BookId:{}获取基金状态,", bookId);
		if (null == bookId) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空！");
		}
		List<BookFundDto> bookFundDtos = bookFundDao.getByBookId(bookId);
		return bookFundDtos;
	}

	/**
	 * 判断书刊基金是否被买断
	 */
	@Override
	public Boolean isFundOccupy(Long bookId, String date) {
		if (null == bookId || null == date) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "参数缺失！");
		}
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("bookId", bookId);
		paramMap.put("date", date);
		List<BookFundDto> bookFundDto = bookFundDao.getByParamMap(paramMap);
		Boolean isOcuppy = false;
		if (null != bookFundDto && bookFundDto.size() != 0) {
			isOcuppy = true;
		}
		LOGGER.info("【书刊管理(内部)】判断书刊基金是否被买断,bookId:{};date:{};bookFundDto:{};isOcuppy:{}", bookId, date, bookFundDto, isOcuppy);
		return isOcuppy;
	}

	/**
	 * 编辑端获取基金买断信息
	 */
	@Override
	public Map<String, Object> getFundList4Adviser(Long bookId) {
		LOGGER.info("【书刊管理(编辑端)】编辑端获取基金买断信息,bookId:{}", bookId);
		if (null == bookId) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空！");
		}
		Map<String, Object> reultMap = new HashMap<>();
		Boolean isOcuppy = null;
		// 获取当前书刊基金状态
		List<BookFundDto> bookFundDto = bookFundDao.getCurrentBookFund(bookId);
		// 已买断状态
		if (null != bookFundDto && bookFundDto.size() != 0) {
			isOcuppy = true;
			reultMap.put("isOcuppy", isOcuppy);
			reultMap.put("bookFundDto", bookFundDto);
		} else {// 未买断状态
			isOcuppy = false;
			reultMap.put("isOcuppy", isOcuppy);
			reultMap.put("bookFundDto", new ArrayList<>());
		}
		return reultMap;
	}

	/**
	 * 批量获取书刊基金总额
	 */
	@Override
	public Map<Long, BigDecimal> getBookFundMoney(List<Long> bookIds) {
		LOGGER.info("【书刊管理(编辑端)】批量获取书刊基金总额,bookIds:{}", bookIds);
		if (null == bookIds || bookIds.size() == 0) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空！");
		}
		Map<Long, BookFundDto> bookFundDtoMap = bookFundDao.getBookFundMoney(bookIds);
		Map<Long, BigDecimal> bookFundMap = new HashMap<>();
		for (Map.Entry<Long, BookFundDto> entry : bookFundDtoMap.entrySet()) {
			if (entry.getValue() != null) {
				bookFundMap.put(entry.getKey(), entry.getValue().getFundMoneySum());
			}
		}
		return bookFundMap;
	}

	/**
	 * 获取图书在基金支持的基金名称
	 */
	@Override
	public String getUseFundName(Long bookId, String useDate) {
		LOGGER.info("【内部】 获取图书在基金支持的基金名称,<START>.[bookId]=" + bookId + "useDate" + useDate);
		if (bookId == null || useDate == null) {
			return null;
		}
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("bookId", bookId);
		paramMap.put("useDate", useDate);
		return bookFundDao.getUseFundName(paramMap);
	}

	/**
	 * 根据BookId获取基金状态
	 */
	@Override
	public PageBean listByBookId(PageParam pageParam, Long bookId) {
		LOGGER.info("根据BookId获取基金状态,bookId:{}", bookId);
		if (null == bookId) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空！");
		}
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("bookId", bookId);
		PageBean pageBean = bookFundDao.listPage(pageParam, paramMap, "listByBookId");
		return pageBean;
	}

	/**
	 * 正在基金支持的图书
	 */
	@Override
	public Long getHaveFundBook(List<Long> bookIds) {
		LOGGER.info("正在基金支持的图书,<START>.[bookIds]:{}", bookIds);
		if (ListUtils.isEmpty(bookIds)) {
			return null;
		}
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("bookIds", bookIds);
		Long bookId = bookFundDao.getHaveFundBook(paramMap);
		return bookId;
	}

	/**
	 * 获取书刊基金状态
	 */
	@Override
	public BookFundDto getByBookFundId(Long bookFundId) {
		LOGGER.info("获取书刊基金状态,<START>.[bookFundId]=" + bookFundId);
		if (null == bookFundId) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "基金标识不能为空！");
		}
		return bookFundDao.getByBookFundId(bookFundId);
	}

	/**
	 * 删除书刊基金
	 */
	@Override
	public void deleteById(Long bookFundId) {
		LOGGER.info("删除书刊基金,<START>.[bookFundId]=" + bookFundId);
		if (null == bookFundId) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "基金标识不能为空！");
		}
		bookFundDao.deleteById(bookFundId);
	}

	/**
	 * 正在基金支持的图书列表
	 */
	@Override
	public List<Long> listHaveFundBooks(List<Long> bookIds) {
		LOGGER.info("正在基金支持的图书列表,bookIds：{}", bookIds);
		if (ListUtils.isEmpty(bookIds)) {
			return null;
		}
		List<Long> fundBookIds = bookFundDao.listHaveFundBooks(bookIds);
		return fundBookIds;
	}

	/**
	 * 获取所有正在基金支持的书
	 */
	@Override
	public List<Long> listAllHaveFundBooks() {
		List<Long> fundBookIds = bookFundDao.listAllHaveFundBooks();
		return fundBookIds;
	}

	@ParamLog(description = "获取图书在基金支持的基金信息【内部调用】")
	@Override
	public BookFundInfoDto getUseFundInfo(Long bookId, String useDate) {
		if (bookId == null || useDate == null) {
			return null;
		}
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("bookId", bookId);
		paramMap.put("useDate", useDate);
		BookFundInfoDto bookFundInfoDto = bookFundDao.getUseFundInfo(paramMap);
		return null == bookFundInfoDto? new BookFundInfoDto():bookFundInfoDto;
	}

	@Override
	@ParamLog("获取图书是否设置过基金（不计算未开始的）(内部调用)")
	public Boolean getIsHaveFundBefore(Long bookId) {
		if(bookId == null) return null;
		Boolean isHaveFundBefore = bookFundDao.getIsHaveFundBefore(bookId);
		return isHaveFundBefore;
	}

	@Override
	public Integer getFundBookCount() {
		return bookFundDao.getFundBookCount();
	}
}
