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

import com.alibaba.druid.util.StringUtils;
import com.pcloud.book.appeal.biz.BookAppealBiz;
import com.pcloud.book.appeal.dao.BookAppealDao;
import com.pcloud.book.appeal.dao.BookAppealResultDao;
import com.pcloud.book.appeal.dao.BookDefendantDao;
import com.pcloud.book.appeal.dto.AppealAdviserDto;
import com.pcloud.book.appeal.dto.BookAppealDto;
import com.pcloud.book.appeal.dto.BookAppealResultDto;
import com.pcloud.book.appeal.entity.BookAppeal;
import com.pcloud.book.appeal.entity.BookAppealResult;
import com.pcloud.book.base.enums.AppealStateEnum;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookAdviserBiz;
import com.pcloud.book.book.biz.BookBiz;
import com.pcloud.book.book.dao.BookAdviserDao;
import com.pcloud.book.book.dto.BookAdviserDto;
import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.book.dto.BookMainAdviserDto;
import com.pcloud.book.book.entity.BookAdviser;
import com.pcloud.book.book.entity.BookDefendant;
import com.pcloud.book.book.set.BookSet;
import com.pcloud.book.consumer.channel.QrcodeSceneConsr;
import com.pcloud.book.consumer.message.TemplateConsr;
import com.pcloud.book.consumer.user.AdviserConsr;
import com.pcloud.book.consumer.user.BookcaseConsr;
import com.pcloud.book.consumer.user.ChannelConsr;
import com.pcloud.book.es.biz.ESBookAndAdviserBiz;
import com.pcloud.book.group.biz.BookGroupBiz;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.common.core.constant.SceneCode;
import com.pcloud.common.core.constant.SendType;
import com.pcloud.common.core.constant.SystemCode;
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 com.pcloud.usercenter.party.adviser.dto.AdviserBaseInfoDto;

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

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 书刊申诉业务处理实现类
 * @version 1.0
 * @author:lili
 * @date 创建时间：2017年3月30日 下午3:51:19
 * @return
 */
@Component("bookAppealBiz")
public class BookAppealBizImpl implements BookAppealBiz {
    /**
     *
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(BookAppealBizImpl.class);

    @Autowired
    private BookAppealDao bookAppealDao;

    @Autowired
    private BookSet bookSet;

    @Autowired
    private TemplateConsr templateConsr;

    @Autowired
    private BookAdviserBiz bookAdviserBiz;

    @Autowired
    private BookcaseConsr bookcaseConsr;

    @Autowired
    private BookBiz bookBiz;

    @Autowired
    private AdviserConsr adviserConsr;

    @Autowired
    private BookAdviserDao bookAdviserDao;

    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;

    @Autowired
    private BookDefendantDao bookDefendantDao;

    @Autowired
    private BookAppealResultDao bookAppealResultDao;

    @Autowired
    private ChannelConsr channelConsr;

    @Autowired
    private BookGroupBiz bookGroupBiz;

    @Autowired
    private ESBookAndAdviserBiz esBookAndAdviserBiz;

    /**
     * 书刊申诉
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(BookAppeal bookAppeal) {
        LOGGER.info("【书籍申诉-编辑】创建书籍申诉信息,<START>.");
        this.checkParam(bookAppeal);
        // 设置申诉时间
        bookAppeal.setAppealSubmitDate(new Date());
        bookAppeal.setAppealState(AppealStateEnum.APPEAL_STATE_WAIT.value);
        if (null == bookAppeal.getIsBookGroup()) {
            bookAppeal.setIsBookGroup(false);
        }
        bookAppealDao.insert(bookAppeal);
    }

    /**
     * 书刊列表
     */
    @Override
    public PageBean list(PageParam pageParam, String bookName, Integer appealState) {
        LOGGER.info("【书籍申诉-平台】获取书籍申诉列表,<START>.");
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("bookName", StringUtils.isEmpty(bookName) ? null : bookName);
        paramMap.put("appealState", appealState);
        PageBean pageBean = bookAppealDao.listPage(pageParam, paramMap, "list");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean();
        }
        // 设置编辑名称
        bookSet.setAdviserName(pageBean.getRecordList());
        return pageBean;
    }

    /**
     * 获取书刊详情
     */
    @Override
    public BookAppealDto getById(Long bookAppealId) {
        LOGGER.info("【书籍申诉-平台】获取书籍申诉详情,<START>.[bookAppealId]" + bookAppealId);
        BookAppealDto bookAppealDto = bookAppealDao.getById(bookAppealId);
        if (bookAppealDto != null) {
            // 获取书籍信息
            BookDto book = bookBiz.getBaseById(bookAppealDto.getBookId());
            bookAppealDto.setBook(book);
            // 设置申诉方以及被诉方基本信息
            bookSet.setAdviserInfo(bookAppealDto);
        }
        return bookAppealDto;

    }

    /**
     * 书刊申诉审核
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setupAudit(BookAppeal bookAppeal) {
        LOGGER.info("【书籍申诉-审核-平台】审核书籍申诉,<START>.参数：[bookAppeal]" + bookAppeal.toString());
        if (bookAppeal.getAppealState() == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "审核状态为空");
        }
        // 获取申诉基本信息
        BookAppealDto bookAppealDto = bookAppealDao.getById(bookAppeal.getBookAppealId());

        // 获取图书详情
        BookDto bookDto = bookBiz.getBaseById(bookAppealDto.getBookId());

        bookAppealDao.update(bookAppeal);

        //获取所有被诉编辑
        List<BookAdviserDto> adviserBooks = bookAdviserDao.getAdvisers(bookAppealDto.getBookId());
        //审核通过
        if (AppealStateEnum.APPEAL_STATE_PASS.value.equals(bookAppeal.getAppealState())) {
            setOnlyOneAdviser(bookAppealDto.getBookId(), bookAppealDto.getDeclarant(), bookAppealDto.getChannelId(), bookAppealDto.getTempletId(),
                    bookAppealDto.getSecondTempletId(), adviserBooks, bookAppealDto.getThirdTempletId());
        }
        // 设置被诉方
        List<BookDefendant> defendants = bookSet.setDefendant(adviserBooks, bookAppeal.getBookAppealId());
        // 添加被诉方
        bookDefendantDao.insert(defendants);
        //新增申诉结果
        insertBookAppealResult(bookAppealDto.getBookId(), bookAppealDto.getBookAppealId());
        ThreadPoolUtils.SEND_MESSAGE_THREAD_POOL.execute((Runnable) () -> {
            //发送模板消息
            if (AppealStateEnum.APPEAL_STATE_REFUSE.value.equals(bookAppeal.getAppealState())) {
                // 向申诉方发送模板消息（审核不通过）
                sendAuditFailTemplate(bookDto.getBookName(), bookAppeal.getAuditReason(), bookAppealDto.getDeclarant(), bookAppealDto.getChannelId());
            } else {
                //发送审核通过模板消息
                sendAuditSuccessTemplate(bookDto.getBookName(), adviserBooks, bookAppealDto.getDeclarant(), bookAppealDto.getChannelId());
            }
        });
    }

    /**
     * 设置申诉结果
     * @param bookId        图书标识
     * @param bookApprealId 图书申诉标识
     */
    @Transactional(rollbackFor = Exception.class)
    void insertBookAppealResult(Long bookId, Long bookApprealId) {
        LOGGER.info("设置申诉结果bookId=" + bookId + "bookApprealId=" + bookApprealId);
        List<BookAdviserDto> adviserBooks = bookAdviserDao.getAdvisers(bookId);
        if (ListUtils.isEmpty(adviserBooks)) {
            return;
        }
        List<BookAppealResult> bookAppealResults = new ArrayList<>();
        for (BookAdviserDto bookAdviserDto : adviserBooks) {
            BookAppealResult bookAppealResult = new BookAppealResult();
            bookAppealResult.setAdviserId(bookAdviserDto.getAdviserId());
            bookAppealResult.setChannelId(bookAdviserDto.getChannelId());
            bookAppealResult.setBookId(bookAdviserDto.getBookId());
            bookAppealResult.setIsMainEditor(bookAdviserDto.getIsMainEditor());
            bookAppealResult.setBookCreatedDate(bookAdviserDto.getCreatedDate());
            bookAppealResult.setBookAppealId(bookApprealId);
            bookAppealResults.add(bookAppealResult);
        }
        bookAppealResultDao.insert(bookAppealResults);
        LOGGER.info("设置申诉结果【END】");
    }

    /**
     * 发送申诉审核通过的模板消息
     * @param bookName     图书名称
     * @param adviserBooks 被诉方
     * @param declarant    申诉方
     */
    void sendAuditSuccessTemplate(String bookName, List<BookAdviserDto> adviserBooks, Long declarant, Long channelId) {
        if (!ListUtils.isEmpty(adviserBooks)) {
            //给被诉方发送图书被移除的通知
            for (BookAdviserDto bookAdviserDto : adviserBooks) {
                removeBookTemplate(bookName, bookAdviserDto.getAdviserId(), bookAdviserDto.getChannelId());
            }
            //给申诉方发送申诉成功的通知
            sendAppealSuccessToMainTemplate(bookName, declarant, channelId);
        }

    }

    /**
     * 参数验证
     * @param bookAppeal
     */
    private void checkParam(BookAppeal bookAppeal) {
        if (null == bookAppeal.getBookId()) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "申诉书籍为空");
        }
        if (StringUtil.isEmpty(bookAppeal.getReason())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "申诉理由为空");
        }
        if (StringUtil.isEmpty(bookAppeal.getPhone())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "联系方式为空");
        }
    }

    /**
     * 获取申诉+被诉编辑
     */
    @Override
    public List<AppealAdviserDto> getAppealAdvisers(Long bookAppealId) {
        LOGGER.info("【书籍申诉-平台】获取申诉+被诉编辑,<START>.[bookAppealId]" + bookAppealId);
        // 获取申诉方信息
        BookAppealDto bookAppealDto = bookAppealDao.getById(bookAppealId);
        List<AppealAdviserDto> appealAdviserList = new ArrayList<AppealAdviserDto>();
        // 获取被诉方信息(即与该书关联的所有编辑)
        List<BookAdviserDto> defendantAdvisers = bookAdviserDao.getAdvisers(bookAppealDto.getBookId());
        // 设置申诉和被诉方列表信息
        bookSet.setAppealAdviserList(appealAdviserList, bookAppealDto, defendantAdvisers);
        return appealAdviserList;
    }

    /**
     * 设置主编辑(共同拥有)
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setMainAdviser(Long auditUser, BookMainAdviserDto bookMainAdviserDto) {
        LOGGER.info("【书籍申诉-平台】设置主编辑,<START>.[bookMainAdviserDto]" + bookMainAdviserDto.toString());
        // 获取申诉基本信息
        BookAppealDto bookAppealDto = bookAppealDao.getById(bookMainAdviserDto.getBookAppealId());
        Long bookId = bookMainAdviserDto.getBookId();
        Long channelId = bookAppealDto.getChannelId();
        Long appealAdviserId = bookAppealDto.getDeclarant();
        //获取加入过该书的所有编辑
        List<BookAdviserDto> adviserBooks = bookAdviserDao.getAdvisers(bookId);
        //申诉后的主编辑
        Long mainAdviserId = null;
        Boolean isOnlyOneAdviser = bookMainAdviserDto.getBookAdviserList().size() == 1;
        if (isOnlyOneAdviser) {//唯一拥有
            setOnlyOneAdviser(bookId, appealAdviserId, bookAppealDto.getChannelId(), bookAppealDto.getTempletId(), bookAppealDto.getSecondTempletId(),
                    adviserBooks, bookAppealDto.getThirdTempletId());
            mainAdviserId = bookMainAdviserDto.getBookAdviserList().get(0).getAdviserId();
        } else {
            for (BookAdviser bookAdviser : bookMainAdviserDto.getBookAdviserList()) {
                bookAdviser.setCreatedUser(bookAdviser.getAdviserId());
                if (bookAdviser.getIsMainEditor()) {
                    //删除书架上书籍
                    ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
                        bookcaseConsr.changeBookAdviser(bookAdviser.getAdviserId(), bookAdviser.getChannelId(), bookAdviser.getBookId());
                    });
                    mainAdviserId = bookAdviser.getAdviserId();
                }
                // 若为申诉编辑，设置申诉编辑图书类型
                if (bookAdviser.getAdviserId().equals(appealAdviserId) && channelId.equals(bookAdviser.getChannelId())) {
                    bookAdviser.setTempletId(bookAppealDto.getTempletId());
                    bookAdviser.setSecondTempletId(bookAppealDto.getSecondTempletId());
                    bookAdviser.setThirdTempletId(bookAppealDto.getThirdTempletId());
                }
            }
            // 批量修改图书编辑关联关系
            bookAdviserDao.insert(bookMainAdviserDto.getBookAdviserList());
            esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(bookId));
            // 新增申诉编辑图书与二维码关联关系
            ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
                recoverBookQrcodeAssoc(bookId, bookAppealDto.getChannelId(), appealAdviserId);
            });
        }
        // 社群书申诉创建社群码
        if (null != bookAppealDto && bookAppealDto.getIsBookGroup()) {
            bookGroupBiz.recoverByBookId(bookId, channelId, appealAdviserId);
            bookGroupBiz.getBookGroupInfoByBookId(bookId, channelId, appealAdviserId, bookAppealDto.getAddType(), null, null, null,null);
        }
        // 修改申诉状态
        this.updateAppealState(auditUser, bookMainAdviserDto.getAppealState(), bookMainAdviserDto.getVersion(),
                bookMainAdviserDto.getBookAppealId());
        // 设置被诉方
        List<BookDefendant> defendants = bookSet.setDefendant(adviserBooks, bookMainAdviserDto.getBookAppealId());
        // 添加被诉方
        bookDefendantDao.insert(defendants);
        //新增申诉结果
        insertBookAppealResult(bookAppealDto.getBookId(), bookAppealDto.getBookAppealId());
        // 发送模板消息
        sendAppealTemplate(isOnlyOneAdviser, appealAdviserId, adviserBooks, bookId, bookAppealDto.getChannelId(), mainAdviserId);
    }

    /**
     * 设置申诉编辑唯一拥有
     * @param bookId    图书标识
     * @param declarant 申诉方
     * @param channelId 运营标识
     * @param templetId 模板标识
     * @param thirdTempletId
     */
    public void setOnlyOneAdviser(Long bookId, Long declarant, Long channelId, Long templetId, Long secondTempletId, List<BookAdviserDto> adviserBooks, Long thirdTempletId) {
        //删除其余编辑与图书关联关系
        bookAdviserBiz.deleteByBook(bookId);
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
            //批量删除书架书籍
            adviserBooks.forEach(
                    adviserBook -> {
                        bookcaseConsr.deleteBookForAdviser(bookId, channelId, adviserBook.getAdviserId());
                        //删除与二维码关联关系
                        qrcodeSceneConsr.deleteBook(bookId, adviserBook.getChannelId(), adviserBook.getAdviserId());
                        // 删除社群码
                        bookGroupBiz.deleteByBookId(bookId, adviserBook.getChannelId(), adviserBook.getAdviserId());
                    }
            );
        });
        //加上申诉编辑与图书关联关系
        BookAdviser bookAdviser = new BookAdviser();
        bookAdviser.setAdviserId(declarant);
        bookAdviser.setChannelId(channelId);
        bookAdviser.setBookId(bookId);
        bookAdviser.setTempletId(templetId);
        bookAdviser.setIsMainEditor(true);
        bookAdviser.setSecondTempletId(secondTempletId);
        bookAdviser.setThirdTempletId(thirdTempletId);
        bookAdviserDao.insert(bookAdviser);
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(bookId));
        // 恢复申诉编辑图书与二维码关联关系
        recoverBookQrcodeAssoc(bookId, channelId, declarant);
    }

    /**
     * 发送申诉审核通过的模板消息
     * @param isOnlyOneAdviser 是否唯一拥有
     * @param appealAdviserId  申诉编辑
     * @param bookAdviserList  审核后编辑与书的关系
     * @param bookId           图书标识
     * @param channelId        运营标识
     */
    private void sendAppealTemplate(Boolean isOnlyOneAdviser, Long appealAdviserId, List<BookAdviserDto> bookAdviserList, Long bookId, Long channelId, Long mainAdviserId) {
        LOGGER.info("发送申诉审核后的模板消息appealAdviserId=" + appealAdviserId + "bookAdviserList=" + bookAdviserList +
                "bookId=" + bookId + "channelId=" + channelId + "mainAdviserId=" + mainAdviserId);
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
            // 获取图书详情
            BookDto bookDto = bookBiz.getBaseById(bookId);
            String bookName = bookDto.getBookName();
            for (BookAdviserDto bookAdviser : bookAdviserList) {
                if (isOnlyOneAdviser) {
                    removeBookTemplate(bookName, bookAdviser.getAdviserId(), bookAdviser.getChannelId());
                } else {
                    //主编辑变为副编辑
                    if (bookAdviser.getIsMainEditor() && !mainAdviserId.equals(bookAdviser.getAdviserId())) {
                        adviserChangeToSubTemplate(bookName, bookAdviser.getAdviserId(), bookAdviser.getChannelId());
                    }
                    //副编辑变为主编辑
                    if (!bookAdviser.getIsMainEditor() && mainAdviserId.equals(bookAdviser.getAdviserId())) {
                        adviserChangeToMainTemplate(bookName, bookAdviser.getAdviserId(), bookAdviser.getChannelId());
                    }
                }
            }
            //给申诉编辑发送模板消息
            if (appealAdviserId.equals(mainAdviserId)) {
                sendAppealSuccessToMainTemplate(bookName, appealAdviserId, channelId);
            } else {
                sendAppealSuccessToSubTemplate(bookName, appealAdviserId, channelId);
            }
            LOGGER.info("发送申诉审核后的模板消息【END】");
        });


    }

    /**
     * 主编辑发生改变，给新主编辑发送模板消息(给新主编辑发消息不包括申诉编辑)
     * @param bookName  图书名称
     * @param adviserId 编辑标识
     */
    void adviserChangeToMainTemplate(String bookName, Long adviserId, Long channelId) {
        LOGGER.info("主编辑发生改变，给新主编辑发送模板消息,bookName=" + bookName + "adviserId=" + adviserId);
        Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
        String channelName = channelConsr.getNameById(channelId);
        Map<String, String> temParam = new HashMap<>();
        temParam.put("first", "编辑变更");
        temParam.put("keyword1", "RAYS编辑");
        temParam.put("keyword2", "您在" + channelName + "运营的书刊" + StringUtil.addBracket(bookName) + "已将您设置为主编辑，请尽快去PC端配置书刊的相关资源等信息");
        temParam.put("remark", "请抽空处理");
        templateConsr.sendManage(SceneCode.PROJECT_TASK_SCENE.value, agentId, adviserId, SystemCode.adviser.code, "",
                temParam, SendType.SEND_BY_PARTY_ID.value, false);
        LOGGER.info(" 主编辑发生改变，给新主编辑发送模板消息[END]");
    }

    /**
     * 书籍被移除模板消息
     * @param bookName  图书名称
     * @param adviserId 编辑标识
     */
    void removeBookTemplate(String bookName, Long adviserId, Long channelId) {
        LOGGER.info("书籍被移除模板消息,bookName=" + bookName + "adviserId=" + adviserId + "channelId=" + channelId);
        Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
        String channelName = channelConsr.getNameById(channelId);
        Map<String, String> temParam = new HashMap<>();
        temParam.put("first", "编辑变更");
        temParam.put("keyword1", "RAYS编辑");
        temParam.put("keyword2", "您在" + channelName + "运营的书刊" + StringUtil.addBracket(bookName) + "被申诉成功，已被移除，请知悉");
        temParam.put("remark", "请抽空处理");
        templateConsr.sendManage(SceneCode.PROJECT_TASK_SCENE.value, agentId, adviserId, SystemCode.adviser.code, "",
                temParam, SendType.SEND_BY_PARTY_ID.value, false);
        LOGGER.info("书籍被移除模板消息[END]");
    }

    /**
     * 主编辑发生改变，由主编辑变为副编辑模板消息
     * @param bookName  图书名称
     * @param adviserId 编辑标识
     */
    void adviserChangeToSubTemplate(String bookName, Long adviserId, Long channelId) {
        LOGGER.info("主编辑发生改变，由主编辑变为副编辑模板消息,bookName=" + bookName + "adviserId=" + adviserId + "channelId=" + channelId);
        Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
        String channelName = channelConsr.getNameById(channelId);
        Map<String, String> temParam = new HashMap<>();
        temParam.put("first", "编辑变更");
        temParam.put("keyword1", "RAYS编辑");
        temParam.put("keyword2", "您在" + channelName + "运营的书刊" + StringUtil.addBracket(bookName) + "被申诉成功，已将您设置为副编辑，请知悉");
        temParam.put("remark", "请抽空处理");
        templateConsr.sendManage(SceneCode.PROJECT_TASK_SCENE.value, agentId, adviserId, SystemCode.adviser.code, "",
                temParam, SendType.SEND_BY_PARTY_ID.value, false);
        LOGGER.info(" 主编辑发生改变，给新主编辑发送模板消息[END]");
    }

    /**
     * 申诉成功为主编辑
     * @param bookName  图书名称
     * @param adviserId 编辑标识
     */
    void sendAppealSuccessToMainTemplate(String bookName, Long adviserId, Long channelId) {
        LOGGER.info("申诉成功为主编辑,bookName=" + bookName + "adviserId=" + adviserId + "channelId=" + channelId);
        // 发送模板消息---申诉编辑变为主编辑(给申诉编辑编辑发消息)
        Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
        String channelName = channelConsr.getNameById(channelId);
        Map<String, String> temParam = new HashMap<>();
        temParam.put("first", "恭喜您,您申请的" + channelName + "运营的书刊" + StringUtil.addBracket(bookName) + "申诉成功");
        temParam.put("keyword2", "书刊申诉审核");
        temParam.put("keyword1", "书刊申诉");
        temParam.put("keyword3", "申诉通过");
        temParam.put("keyword4", DateUtils.formatDate(new Date()));
        temParam.put("remark", "书刊已加入您的书刊列表，您是主编辑，请去PC端配置书刊的相关资源");
        templateConsr.sendManage(SceneCode.TASK_HANDLE_RESULT_SCENE.value, agentId, adviserId, SystemCode.adviser.code,
                "", temParam, SendType.SEND_BY_PARTY_ID.value, false);
        LOGGER.info("申诉成功为主编辑[END]");
    }

    /**
     * 申诉成功为副编辑
     * @param bookName  图书名称
     * @param adviserId 编辑标识
     */
    void sendAppealSuccessToSubTemplate(String bookName, Long adviserId, Long channelId) {
        LOGGER.info("申诉成功为副编辑，给申诉编辑发消息,bookName=" + bookName + "adviserId=" + adviserId + "channelId=" + channelId);
        // 发送模板消息---提交申诉的编辑，申诉成功之后是副编辑(给申诉编辑发消息)
        Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
        String channelName = channelConsr.getNameById(channelId);
        Map<String, String> temParam = new HashMap<>();
        temParam.put("first", "恭喜您,您申请的" + channelName + "运营的书刊" + StringUtil.addBracket(bookName) + "申诉成功");
        temParam.put("keyword2", "书刊申诉审核");
        temParam.put("keyword1", "书刊申诉");
        temParam.put("keyword3", "申诉通过");
        temParam.put("keyword4", DateUtils.formatDate(new Date()));
        temParam.put("remark", "书刊已加入您的书刊列表，您是副编辑，可直接共享书刊配套资源");
        templateConsr.sendManage(SceneCode.TASK_HANDLE_RESULT_SCENE.value, agentId, adviserId, SystemCode.adviser.code,
                "", temParam, SendType.SEND_BY_PARTY_ID.value, false);
        LOGGER.info("申诉成功为副编辑，给申诉编辑发消息【END】");
    }

    /**
     * 发送申诉审核未通过的模板消息
     * @param bookName    图书名称
     * @param auditReason 审核不通过原因
     * @param declarant   申诉方
     */
    void sendAuditFailTemplate(String bookName, String auditReason, Long declarant, Long channelId) {
        try {
            String channelName = channelConsr.getNameById(channelId);
            // 获取申诉人所属代理
            Long agentId = adviserConsr.getAgentIdByAdviser(declarant);
            Map<String, String> temParam = new HashMap<>();
            temParam.put("first", "很抱歉，您申请的" + channelName + "运营的书刊" + StringUtil.addBracket(bookName) + "申诉未通过审核");
            temParam.put("keyword2", "书刊申诉审核");
            temParam.put("keyword1", "书刊申诉");
            temParam.put("keyword3", "申诉不通过");
            temParam.put("keyword4", DateUtils.formatDate(new Date()));
            temParam.put("remark", "申诉不通过，原因：" + auditReason);
            templateConsr.sendManage(SceneCode.TASK_HANDLE_RESULT_SCENE.value, agentId,
                    declarant, SystemCode.adviser.code, "", temParam,
                    SendType.SEND_BY_PARTY_ID.value, false);
        } catch (Exception e) {
            LOGGER.error("【书籍申诉-审核-平台】书刊申诉审核:发送模板消息,<ERROR>:" + e.getMessage(), e);
        }
    }

    /**
     * 修改申诉状态
     * @param auditUser    审核人
     * @param appealState  申诉状态
     * @param version      版本号
     * @param bookAppealId 申诉标识
     */
    @Transactional(rollbackFor = Exception.class)
    void updateAppealState(Long auditUser, Integer appealState, Integer version, Long bookAppealId) {
        LOGGER.info("修改申诉状态auditUser=" + auditUser + "appealState=" + appealState + "version=" + version
                + "bookAppealId=" + bookAppealId);
        BookAppeal bookAppeal = new BookAppeal();
        bookAppeal.setAuditUser(auditUser);
        bookAppeal.setLastModifiedUser(auditUser);
        bookAppeal.setAppealState(appealState);
        bookAppeal.setVersion(version);
        bookAppeal.setBookAppealId(bookAppealId);
        // 更新申诉状态信息
        bookAppealDao.update(bookAppeal);
        LOGGER.info("修改申诉状态【END】");
    }

    /**
     * 恢复主编辑图书与二维码关联关系
     * @param bookId    图书标识
     * @param channelId 运营标识
     * @param adviserId 编辑标识
     */
    @Transactional(rollbackFor = Exception.class)
    void recoverBookQrcodeAssoc(Long bookId, Long channelId, Long adviserId) {
        LOGGER.info("恢复主编辑图书与二维码关联关系,bookId=" + bookId + ",channelId=" + channelId + "adviserId=" + adviserId);
        qrcodeSceneConsr.recoverByBook(bookId, channelId, adviserId);
        LOGGER.info("恢复主编辑图书与二维码关联关系结束");
    }

    /**
     * 获取申诉结果
     */
    @Override
    public List<BookAppealResultDto> getAppealResult(Long bookAppealId) {
        LOGGER.info("获取申诉结果bookAppealId=" + bookAppealId);
        //获取申诉基本信息
        BookAppealDto bookAppealDto = bookAppealDao.getById(bookAppealId);
        if (bookAppealDto == null || bookAppealDto.getCreatedUser() == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "申诉信息不存在");
        }
        Long appealAdviserId = bookAppealDto.getCreatedUser();
        //获取申诉结果
        List<BookAppealResultDto> appealResults = bookAppealResultDao.getAppealResult(bookAppealId);

        if (ListUtils.isEmpty(appealResults)) {
            return new ArrayList<>();
        }

        List<Long> adviserIds = new ArrayList<>();
        List<Long> channelIds = new ArrayList<>();
        appealResults.stream().forEach(
                appealResult -> {
                    if (appealAdviserId.equals(appealResult.getAdviserId())) {
                        appealResult.setAppealAdviser(true);
                    } else {
                        appealResult.setAppealAdviser(false);
                    }
                    if (!adviserIds.contains(appealResult.getAdviserId())) {
                        adviserIds.add(appealResult.getAdviserId());
                    }
                    if (!channelIds.contains(appealResult.getChannelId())) {
                        channelIds.add(appealResult.getChannelId());
                    }
                }
        );

        // 获取基本信息
        Map<Long, AdviserBaseInfoDto> adviserMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
        Map<Long, String> channelNameMap = channelConsr.getNamesByIdList(channelIds);

        appealResults.stream().forEach(
                appealResult -> {
                    if (adviserMap != null) {
                        AdviserBaseInfoDto adviserBaseInfoDto = adviserMap.get(appealResult.getAdviserId());
                        if (adviserBaseInfoDto != null) {
                            appealResult.setAdviserName(adviserBaseInfoDto.getPartyName());
                            appealResult.setAgentName(adviserBaseInfoDto.getAgentName());
                            appealResult.setPhone(adviserBaseInfoDto.getPhoneNum());
                            appealResult.setHeadUrl(adviserBaseInfoDto.getHeadUrl());
                        }
                    }
                    if (channelNameMap != null) {
                        appealResult.setChannelName(channelNameMap.get(appealResult.getChannelId()));
                    }
                    if (appealAdviserId.equals(appealResult.getAdviserId())) {
                        appealResult.setPhone(bookAppealDto.getPhone());
                    }
                }
        );
        LOGGER.info("获取申诉结果[END]");
        return appealResults;
    }

}
