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

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Maps;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookProductBiz;
import com.pcloud.book.book.cache.BookProductCache;
import com.pcloud.book.book.dao.BookProductDao;
import com.pcloud.book.book.dto.BookProductDto;
import com.pcloud.book.book.dto.QaProductDto;
import com.pcloud.book.book.entity.BookProduct;
import com.pcloud.book.book.set.BookSet;
import com.pcloud.book.consumer.comment.CommentConsr;
import com.pcloud.book.consumer.resource.ProductConsr;
import com.pcloud.book.consumer.user.ChannelConsr;
import com.pcloud.comment.product.dto.CommentDisplayDto;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.resourcecenter.base.constants.ProCons;
import com.pcloud.resourcecenter.product.dto.ProductDto;
import com.pcloud.resourcecenter.product.dto.ProductTypeDto;

/**
 * @描述：
 * 
 * @作者：songx
 * @创建时间：2016年12月23日,下午3:59:36 @版本：1.0
 */
@Service("bookProductBiz")
public class BookProductBizImpl implements BookProductBiz {

	/**
	 * 
	 */
	private static final Logger LOGGER = LoggerFactory.getLogger(BookProductBizImpl.class);

	@Autowired
	private BookProductDao bookProductDao;

	@Autowired
	private ProductConsr productConsr;

	@Autowired
	private BookSet bookSet;

	@Autowired
	private CommentConsr commentConsr;

	@Autowired
	private BookProductCache bookProductCache;

	@Autowired
	private ChannelConsr channelConsr;

	/**
	 * 添加书籍作品关联关系
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void create(BookProduct bookProduct) throws BizException {
		// 参数校验
		this.checkParam(bookProduct);
		try {
			LOGGER.info("【书籍-作品-编辑】添加书籍作品关联关系,<START>.[bookProduct]=" + bookProduct.toString());
			bookProductDao.insert(bookProduct);
			LOGGER.info("【书籍-作品-编辑】添加书籍作品关联关系,<END>");
		} catch (DataIntegrityViolationException e) {
			LOGGER.error("【书籍-作品-编辑】添加书籍作品关联关系>>>>>>" + e.getMessage());
			throw new BizException(BookBizException.FREQUENTLY_REQUEST, "请稍等，正在处理中...");
		} catch (Exception e) {
			LOGGER.error("【书籍-作品-编辑】添加书籍作品关联关系,<ERROR>.[bookProductDao.insert]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "添加书籍作品关联关系失败~！");
		}
		// 清除图书应用关联关系
		try {
			bookProductCache.clearOneBookProduct(bookProduct.getBookId(), bookProduct.getChannelId(),
					bookProduct.getCreatedUser());
		} catch (Exception e) {
			LOGGER.error("清除缓存失败bookProduct=" + bookProduct);
		}
	}

	/**
	 * 检验参数
	 * 
	 * @param bookProduct
	 * @throws BizException
	 */
	private void checkParam(BookProduct bookProduct) throws BizException {
		if (bookProduct.getBookId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空~！");
		}
		if (bookProduct.getProductId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "作品标识不能为空~！");
		}
		if (bookProduct.getChannelId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "渠道标识不能为空~！");
		}
	}

	/**
	 * 删除书籍作品关联关系
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delete(Long bookId, Long productId, Long adviserId, Long channelId) throws BizException {
		if (bookId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空~！");
		}
		if (productId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "作品标识不能为空~！");
		}
		if (adviserId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "编辑标识不能为空~！");
		}
		if (channelId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "渠道标识不能为空~！");
		}

		BookProduct bookProduct = new BookProduct();
		bookProduct.setBookId(bookId);
		bookProduct.setProductId(productId);
		bookProduct.setCreatedUser(adviserId);
		bookProduct.setChannelId(channelId);

		try {
			LOGGER.info("【书籍-作品-编辑】删除书籍作品关联关系,<START>.[bookProduct]=" + bookProduct.toString());
			bookProductDao.delete(bookProduct);
			LOGGER.info("【书籍-作品-编辑】删除书籍作品关联关系,<END>");
		} catch (Exception e) {
			LOGGER.error("【书籍-作品-编辑】删除书籍作品关联关系,<ERROR>.[bookProductDao.delete]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "删除书籍作品关联关系失败~！");
		}
		// 清除图书应用关联关系
		try {
			bookProductCache.clearOneBookProduct(bookId, channelId, adviserId);
		} catch (Exception e) {
			LOGGER.error("清除缓存失败bookProduct=" + bookProduct);
		}
	}

	/**
	 * 根据书籍删除作品关联关系
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteByBook(Long bookId) throws BizException {
		if (bookId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空~！");
		}

		try {
			LOGGER.info("【书籍-作品-编辑】根据书籍删除作品关联关系,<START>.[bookId]=" + bookId);
			bookProductDao.deleteByBook(bookId);
			LOGGER.info("【书籍-作品-编辑】根据书籍删除作品关联关系,<END>");
		} catch (Exception e) {
			LOGGER.error("【书籍-作品-编辑】根据书籍删除作品关联关系,<ERROR>.[bookDao.insert]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "删除作品关联关系失败~！");
		}
		// 清除图书应用关联关系
		try {
			bookProductCache.clearBookProduct(bookId);
		} catch (Exception e) {
			LOGGER.error("清除缓存失败");
		}
	}

	/**
	 * 批量删除作品关联关系
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteByBooks(List<Long> bookIds) throws BizException {
		if (bookIds == null || bookIds.isEmpty()) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空~！");
		}

		try {
			LOGGER.info("【书籍-作品-编辑】批量删除作品关联关系,<START>.[bookIds]=" + bookIds.toString());
			bookProductDao.deleteByBooks(bookIds);
			LOGGER.info("【书籍-作品-编辑】批量删除作品关联关系,<END>");
		} catch (Exception e) {
			LOGGER.error("【书籍-作品-编辑】批量删除作品关联关系,<ERROR>.[bookProductDao.deleteByBooks]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "批量删除作品关联关系失败~！");
		}
		try {
			for (Long bookId : bookIds) {
				bookProductCache.clearBookProduct(bookId);
			}
		} catch (Exception e) {
			LOGGER.error("清除缓存失败");
		}
	}

	/**
	 * 获取书籍关联的作品
	 */
	@Override
	public List<BookProductDto> getListById(Long bookId, Long adviserId, Long channelId) throws BizException {
		if (bookId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空~！");
		}
		if (adviserId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "顾问标识不能为空~！");
		}
		if (channelId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "渠道标识不能为空~！");
		}
		// 从缓存中读取书籍与商品关联关系
		List<BookProductDto> listBookProductAssoc = bookProductCache.listBookProductAssoc(bookId, channelId, adviserId);
		if (ListUtils.isEmpty(listBookProductAssoc)) {
			BookProduct bookProduct = new BookProduct();
			bookProduct.setBookId(bookId);
			bookProduct.setChannelId(channelId);
			bookProduct.setCreatedUser(adviserId);
			try {
				LOGGER.info("【书籍-作品-编辑】获取书籍关联的作品,<START>.[bookProduct]=" + bookProduct.toString());
				listBookProductAssoc = bookProductDao.getListById(bookProduct);
				if (listBookProductAssoc == null) {
					listBookProductAssoc = new ArrayList<>();
				} else {
					bookProductCache.setBookProductAssoc(bookId, channelId, adviserId, listBookProductAssoc);
				}
				LOGGER.info("【书籍-作品-编辑】获取书籍关联的作品,<END>.[listBookProductAssoc]=" + listBookProductAssoc);
			} catch (Exception e) {
				LOGGER.error("【书籍-作品-编辑】获取书籍关联的作品,<ERROR>.[bookProductDao.getListById]:" + e.getMessage(), e);
				throw BizException.DB_SELECT_IS_FAIL;
			}
		}
		return listBookProductAssoc;
	}

	/**
	 * 获取书籍关联的作品,包含作品基础信息(过滤问答)
	 */
	@Override
	public List<Object> getProListById(Long bookId, Long adviserId, Long channelId) throws BizException {
		List<BookProductDto> bookProductDtos = this.getListById(bookId, adviserId, channelId);
		List<Long> productIds = new ArrayList<>();
		List<Object> products = new ArrayList<>();
		// 只取问答数据
		for (BookProductDto bookProductDto : bookProductDtos) {
			if (!ProCons.QA.equals(bookProductDto.getProductType())) {
				productIds.add(bookProductDto.getProductId());
			}
		}
		Map<Long, ProductDto> productMap = productConsr.listProDetail4Wechat(productIds, channelId);
		if (MapUtils.isEmpty(productMap)) {
			return new ArrayList<Object>();
		}

		for (BookProductDto bookProductDto : bookProductDtos) {
			if (ProCons.QA.equals(bookProductDto.getProductType())) {
				continue;
			}
			ProductDto productDto = productMap.get(bookProductDto.getProductId());
			if (productDto != null) {
				if (productDto.getIsSale()) {
					ProductDto newProduct = new ProductDto();
					newProduct.setProductId(bookProductDto.getProductId());
					newProduct.setProductName(productDto.getProductName());
					newProduct.setVideoId(bookProductDto.getSoundId());
					newProduct.setCoverImg(productDto.getCoverImg());
					newProduct.setDescription(productDto.getDescription());
					newProduct.setProductTypeName(productDto.getProductTypeName());
					newProduct.setProductTypeCode(productDto.getProductTypeCode());
					products.add(newProduct);
				}
			}
		}
		return products;
	}

	/**
	 * 获取书籍关联的问答,包含问答基础信息
	 */
	@Override
	public List<Object> getQaListById(Long bookId, Long adviserId, Long channelId) throws BizException {
		List<BookProductDto> bookProductDtos = this.getListById(bookId, adviserId, channelId);
		List<Long> productIds = new ArrayList<>();
		List<Object> products = new ArrayList<>();
		// 只取问答数据
		for (BookProductDto bookProductDto : bookProductDtos) {
			if (ProCons.QA.equals(bookProductDto.getProductType())) {
				productIds.add(bookProductDto.getProductId());
			}
		}
		if (ListUtils.isEmpty(productIds)) {
			return new ArrayList<Object>();
		}
		// 获取代理标识
		Long agentId = channelConsr.getParentId(channelId);
		Map<Long, ProductDto> qaProMap = productConsr.getQaProRetailBase4Group(productIds, channelId, agentId);
		Map<Long, CommentDisplayDto> commentMap = commentConsr.getCommentFavorableRateByProductIds(productIds);
		// 只取问答数据
		for (BookProductDto bookProductDto : bookProductDtos) {
			if (!ProCons.QA.equals(bookProductDto.getProductType())) {
				continue;
			}
			if (qaProMap != null) {
				ProductDto product = qaProMap.get(bookProductDto.getProductId());
				if (product != null && product.getIsSale()) {
					QaProductDto qaProductDto = new QaProductDto();
					qaProductDto.setProductId(bookProductDto.getProductId());
					qaProductDto.setAuthorName(product.getMerchantName());
					qaProductDto.setCoverImg(product.getCoverImg());
					qaProductDto.setMerchantSkill(product.getMerchantSkill());
					qaProductDto.setMerchantTitle(product.getMerchantTitle());
					qaProductDto.setDetailDesc(product.getDetailDesc());
					qaProductDto.setVedioId(bookProductDto.getSoundId());
					if (commentMap != null && commentMap.get(qaProductDto.getProductId()) != null) {
						CommentDisplayDto commentDisplayDto = commentMap.get(qaProductDto.getProductId());
						qaProductDto.setFavorableRate(commentDisplayDto.getFavorableRate());
					}
					products.add(qaProductDto);
				}
			}
		}

		return products;
	}

	/**
	 * 根据书籍和渠道删除书籍商品关联信息
	 */
	@Override
	public void deleteByBookAndChannel(Long bookId, Long channelId) throws BizException {
		LOGGER.info("【编辑书刊】根据书籍和渠道删除书籍商品关联信息,<START>.[bookId]=" + bookId + ",[channelId]=" + channelId);
		try {
			Map<String, Object> paramMap = Maps.newHashMap();
			paramMap.put("bookId", bookId);
			paramMap.put("channelId", channelId);
			bookProductDao.deleteByBookAndChannel(paramMap);
		} catch (Exception e) {
			LOGGER.error("【编辑书刊】根据书籍和渠道删除书籍商品关联信息,<ERROR>.[deleteByBookAndChannel]:" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "根据书籍和渠道删除书籍商品关联信息失败");
		}
		try {
			bookProductCache.clearBookProduct(bookId);
		} catch (Exception e) {
			LOGGER.error("清除缓存信息失败");
		}
	}

	/**
	 * 设置录音
	 */
	@Override
	public void setSound(BookProduct bookProduct, Long adviserId) {
		LOGGER.info("【编辑书刊】设置商品录音,<START>.[bookProduct]=" + bookProduct);
		try {
			bookProductDao.update(bookProduct);
		} catch (Exception e) {
			LOGGER.error("【编辑书刊】设置商品录音,<ERROR>.[setSound]:" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "设置商品录音失败");
		}
		// 清除缓存
		bookProductCache.clearOneBookProduct(bookProduct.getBookId(), bookProduct.getChannelId(), adviserId);
	}

	/**
	 * 获取书籍关联作品
	 */
	@Override
	public Map<Long, BookProductDto> getMapById(Long bookId, Long adviserId, Long channelId) {
		if (bookId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空~！");
		}
		if (adviserId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "顾问标识不能为空~！");
		}
		if (channelId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "渠道标识不能为空~！");
		}

		List<BookProductDto> bookProductDtos = getListById(bookId, adviserId, channelId);
		// 设置录音
		return bookSet.setSoundInfoAndToMap(bookProductDtos);

	}

	/**
	 * 清除录音
	 */
	@Override
	public void clearSound(Long videoId) {
		LOGGER.info("【图书商品】修改录音.<START>.[videoId]=" + videoId);
		long result = bookProductDao.cleanSound(videoId);
		if (result < 1) {
			return;
		}
		// 清除缓存数据
		try {
			// 获取录音相关的图书商品关联
			List<BookProductDto> bookProductDtos = bookProductDao.listBySoundId(videoId);
			for (BookProductDto bookProductDto : bookProductDtos) {
				bookProductCache.clearOneBookProduct(bookProductDto.getBookId(), bookProductDto.getChannelId(),
						bookProductDto.getCreatedUser());
			}
		} catch (Exception e) {
			LOGGER.error("清除录音失败");
		}

		LOGGER.info("【图书商品】修改录音.<END>");
	}

	/**
	 * 更新商品类型
	 */
	@Override
	public void updateProductType() {
		LOGGER.info("【图书商品】更新商品类型.<START>.");
		// 获取所有图书关联商品
		List<BookProductDto> allBookProduct = bookProductDao.getAllBookProduct();
		if (ListUtils.isEmpty(allBookProduct)) {
			return;
		}
		List<Long> productIds = new ArrayList<>();
		for (BookProductDto bookProductDto : allBookProduct) {
			productIds.add(bookProductDto.getProductId());
		}

		// 获取作品信息
		Map<Long, ProductDto> productMap = productConsr.getProBasesByIds(productIds);
		if (MapUtils.isEmpty(productMap)) {
			return;
		}
		// 设置作品信息
		for (BookProductDto bookProductDto : allBookProduct) {
			ProductDto productDto = productMap.get(bookProductDto.getProductId());
			if (productDto != null) {
				ProductTypeDto productTypeDto = productDto.getProductTypeDto();
				if (productTypeDto != null) {
					bookProductDto.setProductType(productTypeDto.getTypeCode());
				}
			}
		}
		bookProductDao.updateProductType(allBookProduct);

	}

	/**
	 * 获取图书关联作品
	 */
	@Override
	public List<BookProductDto> list4Adviser(Long bookId, Long channelId, Long adviserId) {
		LOGGER.info(
				"【书刊】获取图书关联作品,<START>.[bookId]=" + bookId + ",[channelId]=" + channelId + "[adviserId]=" + adviserId);
		// 获取图书
		List<BookProductDto> bookProductAssoc = getListById(bookId, adviserId, channelId);
		// 设置作者录音
		bookSet.setIsHaveSound(bookProductAssoc);
		// 设置商品基本信息
		bookSet.setProductInfo(bookProductAssoc, channelId);
		return bookProductAssoc;
	}

	/**
	 * 获取图书关联超级作者商品个数
	 */
	@Override
	public Integer getSuperProCount(Long adviserId, Long bookId, Long channelId) {
		LOGGER.info("【编辑书刊】获取图书关联超级作者商品个数,<START>.[bookId]=" + bookId + ",[channelId]=" + channelId + "[adviserId]="
				+ adviserId);
		try {
			Map<String, Object> paramMap = Maps.newHashMap();
			paramMap.put("bookId", bookId);
			paramMap.put("channelId", channelId);
			paramMap.put("adviserId", adviserId);
			return bookProductDao.getSuperProCount(paramMap);
		} catch (Exception e) {
			LOGGER.error("【编辑书刊】获取图书关联超级作者商品个数,<ERROR>.[getSuperProCount]:" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "获取图书关联超级作者商品个数失败");
		}
	}

	/**
	 * 获取图书关联商品个数
	 */
	@Override
	public Integer getProCount(Long adviserId, Long bookId, Long channelId) {
		LOGGER.info("【编辑书刊】 获取图书关联商品个数,<START>.[bookId]=" + bookId + ",[channelId]=" + channelId + "[adviserId]="
				+ adviserId);
		try {
			Map<String, Object> paramMap = Maps.newHashMap();
			paramMap.put("bookId", bookId);
			paramMap.put("channelId", channelId);
			paramMap.put("adviserId", adviserId);
			return bookProductDao.getProCount(paramMap);
		} catch (Exception e) {
			LOGGER.error("【编辑书刊】 获取图书关联商品个数,<ERROR>.[getProCount]:" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, " 获取图书关联商品个数失败");
		}
	}
}
