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

import com.google.common.collect.Maps;

import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookAppBiz;
import com.pcloud.book.book.cache.BookAppCache;
import com.pcloud.book.book.dao.BookAppDao;
import com.pcloud.book.book.dto.BookAppDto;
import com.pcloud.book.book.entity.BookApp;
import com.pcloud.book.book.set.BookSet;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.utils.ListUtils;

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 java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

	/**
	 * 
	 */
	private static final Logger LOGGER = LoggerFactory.getLogger(BookAppBizImpl.class);
	
	@Autowired
	private BookAppDao bookAppDao;
	
	@Autowired
	private BookAppCache bookAppCache;
	
	@Autowired
	private BookSet bookSet;
	
	/**
	 * 创建书刊应用关联关系
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void create(BookApp bookApp) throws BizException {
		LOGGER.info("【书籍-应用-编辑】创建书刊应用关联,bookApp:{}", bookApp);
		// 校验参数
		this.checkParam(bookApp);

		try {
			bookAppDao.insert(bookApp);
		}catch (DataIntegrityViolationException e) {
			LOGGER.error("【书籍-应用-编辑】创建书刊应用关联,已关联过>>>>>>" + e.getMessage());
			throw new BookBizException(BookBizException.DB_DML_FAIL, "请稍等，正在处理中...");
		} catch (Exception e) {
			LOGGER.error("【书籍-应用-编辑】创建书刊应用关联,<ERROR>.[bookDao.insert]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "创建书刊应用关联失败~！");
		}
		// 清除图书应用关联关系
		try {
			if (bookApp != null) {
				bookAppCache.clearOneBookApp(bookApp.getBookId(), bookApp.getChannelId(),
						bookApp.getCreatedUser());
			}
		} catch (Exception e) {
			LOGGER.error("清除缓存失败bookApp="+bookApp);
		}
	}

	/**
	 * 批量创建书刊应用关联
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public void createBatch(List<Long> bookIds, Long channelId, Long appId, Long adviserId) {
		LOGGER.info("【书籍-应用-编辑】批量创建书刊应用关联,<START>.[bookIds]=" + bookIds+"channelId="+channelId+"appId="+appId+"adviserId="+adviserId);
		if(ListUtils.isEmpty(bookIds) || channelId == null || appId == null || adviserId == null){
			return ; 
		}
		List<BookApp> bookApps = new ArrayList<>();
		for(Long bookId : bookIds){
			BookApp bookApp = new BookApp();
			bookApp.setAppId(appId);
			bookApp.setChannelId(channelId);
			bookApp.setCreatedUser(adviserId);
			bookApp.setBookId(bookId);
			//清除图书下缓存
			bookAppCache.clearOneBookApp(bookApp.getBookId(), bookApp.getChannelId(),
					bookApp.getCreatedUser());
			bookApps.add(bookApp);
		}
	   //删除应用关联的所有图书
		deleteByAppId(appId,channelId, adviserId);
		//批量关联应用与图书关联关系
		bookAppDao.insert(bookApps);
	}
	
	
	/**
	 * 删除应用关联的所有图书
	 * @param appId
	 * @param channelId
	 * @param adviserId
	 */
	private void deleteByAppId(Long appId, Long channelId, Long adviserId) {
		LOGGER.info("删除应用关联的所有图书,appId="+appId+"channelId="+channelId+"adviserId="+adviserId);
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("appId", appId);
		paramMap.put("channelId", channelId);
		paramMap.put("adviserId", adviserId);
		bookAppDao.deleteByAppId(paramMap);
	}

	/**
	 * 检验参数
	 */
	private void checkParam(BookApp bookApp) throws BizException {
		if (bookApp.getBookId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊");
		}
		if (bookApp.getAppId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择应用");
		}
		if (bookApp.getChannelId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择运营平台");
		}
	}
	
	/**
	 * 删除书刊应用关联
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void delete(Long bookAppId) throws BizException {
		if (bookAppId == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择应用");
		}

		BookAppDto bookAppDto = bookAppDao.getByBookAppId(bookAppId);
		try {
			LOGGER.info("【书籍-应用-编辑】删除书刊应用关联,<START>.[bookAppId]=" + bookAppId);
			bookAppDao.deleteById(bookAppId);
		} catch (Exception e) {
			LOGGER.error("【书籍-应用-编辑】删除书刊应用关联,<ERROR>.[bookDao.deleteById]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "删除书刊应用关联失败~！");
		}

		// 清除图书应用关联关系
		try {
			if (bookAppDto != null) {
				bookAppCache.clearOneBookApp(bookAppDto.getBookId(), bookAppDto.getChannelId(),
						bookAppDto.getCreatedUser());
			}
		} catch (Exception e) {
			LOGGER.error("清除缓存失败");
		}
	}
	
	/**
	 * 根据书籍删除关联的应用
	 */
	@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);
			bookAppDao.deleteByBook(bookId);
		} catch (Exception e) {
			LOGGER.error("【书籍-应用-编辑】根据书籍删除关联的应用,<ERROR>.[bookDao.deleteByBook]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "根据书籍删除关联的应用失败~！");
		}
		bookAppCache.clearBookApp(bookId);
	}
	
	/**
	 * 批量删除应用关联关系
	 */
	@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());
			bookAppDao.deleteByBooks(bookIds);
		} catch (Exception e) {
			LOGGER.error("【书籍-应用-编辑】批量删除应用关联关系,<ERROR>.[bookDao.deleteByBooks]" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "批量删除应用关联关系失败~！");
		}
		try {
			for (Long bookId : bookIds) {
				bookAppCache.clearBookApp(bookId);
			}
		} catch (Exception e) {
			LOGGER.error("清除缓存失败");
		}
	}

	/**
	 * 获取单个书籍和应用关联关系
	 */
	@Override
	public List<BookAppDto> listBaseById(BookApp bookApp) throws BizException {
		LOGGER.info("【书籍-应用-编辑】获取单个书籍和应用关联关系,[bookApp]:{}", bookApp);
		// 校验参数
		if (bookApp.getBookId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍标识不能为空~！");
		}
		if (bookApp.getCreatedUser() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "顾问标识不能为空~！");
		}
		if (bookApp.getChannelId() == null) {
			throw new BookBizException(BookBizException.PARAM_IS_NULL, "渠道标识不能为空~！");
		}
		//从缓存中读取书籍与应用关联关系
		List<BookAppDto> listBookAppAssoc = bookAppCache.listBookAppAssoc(bookApp.getBookId(), bookApp.getChannelId(), bookApp.getCreatedUser());
		if(ListUtils.isEmpty(listBookAppAssoc)){
			try {
				listBookAppAssoc = bookAppDao.listBaseById(bookApp);
				if (listBookAppAssoc == null) {
					listBookAppAssoc = new ArrayList<>();
				}else{
					bookAppCache.setBookAppAssoc(bookApp.getBookId(), bookApp.getChannelId(), bookApp.getCreatedUser(), listBookAppAssoc);
				}
			} catch (Exception e) {
				LOGGER.error("【书籍-应用-编辑】获取单个书籍和应用关联关系,<ERROR>.[bookAppDao.getById]:" + e.getMessage(), e);
				throw BizException.DB_SELECT_IS_FAIL;
			}
		}
		return listBookAppAssoc;
	}
	
	/**
	 * 获取书籍关联的应用(过滤审核不通过的与过期的应用)
	 */
	@Override
	public List<BookAppDto> getListById(Long bookId, Long adviserId, Long channelId) throws BizException {
		BookApp bookApp = new BookApp();
		bookApp.setBookId(bookId);
		bookApp.setChannelId(channelId);
		bookApp.setCreatedUser(adviserId);
		List<BookAppDto> bookAppDtos = this.listBaseById(bookApp);
		//获取应用信息填充应用基本信息(过滤审核不通过的与过期的应用)
	    return bookSet.setPassAppInfo(bookAppDtos);
	}
	
	/**
	 * 根据书籍和渠道删除书籍应用关联信息
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	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);
			bookAppDao.deleteByBookAndChannel(paramMap);
		} catch (Exception e) {
			LOGGER.error("【编辑书刊】根据书籍和渠道删除书籍应用关联信息,<ERROR>.[deleteByBookAndChannel]:" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "根据书籍和渠道删除书籍应用关联信息失败");
		}
	}

	/**
	 * 获取书籍关联应用
	 */
	@Override
	public List<BookAppDto> getListById4Adviser(Long bookId, Long adviserId, Long channelId) {
		LOGGER.info("【编辑书刊】 获取书籍关联应用,<START>.[bookId]=" + bookId+",[channelId]=" + channelId+",adviserId="+adviserId);
		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, "渠道标识不能为空~！");
		}
		BookApp bookApp = new BookApp();
		bookApp.setBookId(bookId);
		bookApp.setChannelId(channelId);
		bookApp.setCreatedUser(adviserId);
		List<BookAppDto> bookAppDtos = this.listBaseById(bookApp);
		bookSet.setAppInfo(bookAppDtos);
		return bookAppDtos;
	}
	
	/**
	 * 获取图书关联应用个数
	 */
	@Override
	public Integer getAppCount(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 bookAppDao.getAppCount(paramMap);
		} catch (Exception e) {
			LOGGER.error("【编辑书刊】获取图书关联资源个数,<ERROR>.[getAppCount]:" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "获取图书关联应用个数失败");
		}
	}

	/**
	 * 修改书籍应用关系 1删除 0未删除
	 */
	@Override
	public void updateBookAppStatus(Long bookId, Long channelId, Integer status, Long adviserId) {
		LOGGER.info("修改书籍应用关系,<START>.[bookId]=" + bookId+",[channelId]=" + channelId+"[adviserId]="+adviserId+"status="+status);
		try{
			Map<String, Object> paramMap = new HashMap<String, Object>();
			paramMap.put("bookId", bookId);
			paramMap.put("channelId", channelId);
			paramMap.put("status", status);
			paramMap.put("adviserId", adviserId);
			bookAppDao.updateBookApp4Adviser(paramMap);
		}catch (Exception e) {
			LOGGER.error("修改书籍应用关系,<ERROR>.[updateBookAppStatus]:" + e.getMessage(), e);
			throw new BookBizException(BookBizException.DB_DML_FAIL, "修改书籍应用关系失败");
		}
	}

}
