package cn.common.service.impl;

import cn.common.common.constants.BaseConstant;
import cn.common.common.enums.ErrorCode;
import cn.common.common.utils.ValidationUtil;
import cn.common.common.utils.collection.CollectionUtils;
import cn.common.common.utils.common.BaseUtil;
import cn.common.common.utils.common.CheckParam;
import cn.common.common.exception.BusinessException;
import cn.common.interaction.helper.PageBuilder;
import cn.common.req.MessageReplyAddReq;
import cn.common.req.MessageReplyReq;
import cn.common.req.MessageReplyUpdateReq;
import cn.common.interaction.resp.page.Pagination;
import cn.common.resp.MessageReplyResp;
import cn.common.req.MessageReplyImportReq;
import cn.common.resp.MessageReplyExportResp;
import cn.common.repository.entity.MessageReply;
import cn.common.repository.repository.MessageReplyRepository;
import cn.common.service.AuthUserService;
import cn.common.service.MessageReplyService;
import cn.common.common.utils.ExportExcelHandler;
import cn.common.req.base.BaseDeleteReq;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.common.common.utils.spring.SnowflakeIdWorker;
import com.google.common.collect.Lists;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import com.google.common.collect.Maps;
import java.util.Map;

/**
* @author Singer create by Singer email:singer-coder@qq.com
* @packageName cn.common.service
* @Description: 留言回复信息相关服务方法实现
* @date 2021-04-23
*/
@Service("messageReplyService")
@Slf4j
public class MessageReplyServiceImpl implements MessageReplyService {

    @Resource
    private MessageReplyRepository messageReplyRepository;

    @Resource
    private MapperFacade mapperFacade;

    @Resource
    private BaseConstant baseConstant;

    @Resource
    private AuthUserService authUserService;

    @Resource
    private HttpServletResponse response;

    @Resource
    private HttpServletRequest request;

    /**
    * 导出数据
    * @author: create by singer - Singer email:singer-coder@qq.com
    * @date 2022/3/21
    * @param pageReq
    * @return java.util.List
    */
    @Override
    public void exportData(MessageReplyReq pageReq){
        log.info(">>>>>>>>>>>>>>>>>数据导出Req {} <<<<<<<<<<<<<<<<", JSON.toJSONString(pageReq));
        //构建查询条件
        LambdaQueryWrapper<MessageReply> pageWrapper = new LambdaQueryWrapper<>();
        setPageCriteria(pageWrapper,pageReq);
        pageWrapper.orderBy(true,false,MessageReply::getCreateTime);
        List<MessageReply> pageList = messageReplyRepository.selectList(pageWrapper);
        if (CollectionUtils.isEmpty(pageList)) {
            return;
        }
        List<MessageReplyExportResp> respList =
            mapperFacade.mapAsList(pageList, MessageReplyExportResp.class);
        try {
            String fileName = "导出信息.xlsx";
            ExportExcelHandler.setExportResponse(response,fileName);
            ExcelWriter excelWriter = null;
            try {
                // 这里 需要指定写用哪个class去写
                excelWriter = EasyExcel.write(response.getOutputStream(), MessageReplyExportResp.class).build();
                // 这里注意 如果同一个sheet只要创建一次
                WriteSheet writeSheet = EasyExcel.writerSheet("sheet").build();
                excelWriter.write(respList,writeSheet);
            } finally {
                // 关闭流
                if (excelWriter != null) {
                    excelWriter.finish();
                }
            }
        } catch (Exception e) {
            log.error(">>>>>>>>>>>>>>>>>>>>>导出数据异常:{},{}<<<<<<<<<<<<<<<<<<<<<<",e.getMessage(),e);
            ExportExcelHandler.setExportErrorResponse(response);
            Map<String, String> map = Maps.newHashMap();
            try {
                response.getWriter().println(JSON.toJSONString(map));
            } catch (IOException ioException) {
                log.error(">>>>>>>>>>>>>>>>>导出数据发生异常:{},{}<<<<<<<<<<<<<<<<<",e.getMessage(),e);
                ioException.printStackTrace();
            }
        }
    }

    /**
    * 数据导入
    * @author: create by singer - Singer email:singer-coder@qq.com
    * @date 2022/3/21
    * @param file 文件
    * @return
    */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void importData(MultipartFile file){
        try{
            List<MessageReplyImportReq> dataList = EasyExcel
                .read(file.getInputStream()).head(MessageReplyImportReq.class).sheet().doReadSync();
            if(CollectionUtils.isEmpty(dataList)){
                return;
            }
            //进行必要的字段校验
            ValidationUtil.validate(dataList);
            dataList.stream().forEach(item -> {
                MessageReply entity = mapperFacade.map(item, MessageReply.class);
                try {
                    String authUserId = authUserService.currentAuthUserId();
                    BaseUtil.setFieldValueNotNull(entity);
                    entity.setMessageReplyId(SnowflakeIdWorker.uniqueMainId());
                    entity.setOperatorId(authUserId);
                } catch (Exception e) {
                    log.error("导入->设置为空的属性失败 {} , {} ",e.getMessage(),e);
                }
                messageReplyRepository.insert(entity);
            });
        }catch (Exception e){
            log.info(">>>>>>>>>>导入数据出现异常:{},{}<<<<<<<<<",e.getMessage(),e);
            throw new BusinessException(ErrorCode.IMPORT_ERROR_CODE.getCode(),
                ErrorCode.IMPORT_ERROR_CODE.getMessage()+StrUtil.COLON+e.getMessage());
        }
    }

    /**
     * 新增
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/2/15
     * @param addReq 新增Req
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
        public void addItem(MessageReplyAddReq addReq){
        log.info(">>>>>>>>>>>>>>>>>新增Req {} <<<<<<<<<<<<<<<<", JSON.toJSONString(addReq));
        String authUserId = authUserService.currentAuthUserId();
        MessageReply entity = mapperFacade.map(addReq, MessageReply.class);
        try {
            BaseUtil.setFieldValueNotNull(entity);
        } catch (Exception e) {
            log.error("新增->设置为空的属性失败 {} , {} ",e.getMessage(),e);
            throw new BusinessException(ErrorCode.SET_EMPTY_FIELD_ERROR.getCode()
            ,ErrorCode.SET_EMPTY_FIELD_ERROR.getMessage());
        }
        entity.setMessageReplyId(SnowflakeIdWorker.uniqueMainId());
        entity.setOperatorId(authUserId);
        messageReplyRepository.insert(entity);
    }

    /**
     * 批量删除信息
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/2/2
     * @param req 需要被删除的信息
     */
    @Override
    public void batchDeleteItem(BaseDeleteReq req){
        List<String> mainIdList = req.getMainIdList();
        if(CollectionUtils.isEmpty(mainIdList)) {
            return;
        }
        List<MessageReply> entityList = messageReplyRepository.selectList(
            new LambdaQueryWrapper<MessageReply>().in(MessageReply::getMessageReplyId,mainIdList));
        entityList.stream().forEach(item -> {
            messageReplyRepository.deleteById(item);
        });
    }

    /**
    * 查询所有信息
    * @author: create by singer - Singer email:singer-coder@qq.com
    * @date 2022/3/13
    * @param
    * @return java.util.List
    */
    @Override
    public List<MessageReplyResp> queryAllMessageReply(){
        List<MessageReply> entityList = messageReplyRepository.selectList(new LambdaQueryWrapper<>());
            if(CollectionUtils.isEmpty(entityList)){
            return Lists.newArrayList();
        }
        return mapperFacade.mapAsList(entityList,MessageReplyResp.class);
    }


    /**
      * 根据留言ID查询留言信息
      * @author: create by singer - Singer email:singer-coder@qq.com
      * @date 2022/4/12
      * @param messageWordId 留言ID
      * @return java.util.List
      */
    @Override
    public List<MessageReplyResp> queryByMessageWordId(String messageWordId){
        List<MessageReply> entityList = messageReplyRepository.selectList(new LambdaQueryWrapper<MessageReply>()
                .eq(MessageReply::getMessageWordId,messageWordId));
        if(CollectionUtils.isEmpty(entityList)){
            return Lists.newArrayList();
        }
        return mapperFacade.mapAsList(entityList,MessageReplyResp.class);
    }

    /**
     * 分页查询
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/2/15
     * @param  pageReq 分页查询Req
     * @return Pagination
     */
    @Override
    public Pagination<MessageReplyResp> queryByPage(
        MessageReplyReq pageReq){
        log.info(">>>>>>>>>>>>>>>>>分页查询Req {} <<<<<<<<<<<<<<<<", JSON.toJSONString(pageReq));
        //构建查询条件
        LambdaQueryWrapper<MessageReply> pageWrapper = new LambdaQueryWrapper<>();
        setPageCriteria(pageWrapper,pageReq);
        pageWrapper.orderBy(true,false,MessageReply::getCreateTime);
        //开始分页
        Page<Object> page = PageHelper.startPage(pageReq.getCurrentPage(), pageReq.getItemsPerPage());
        List<MessageReply> pageList = messageReplyRepository.selectList(pageWrapper);
        if (CollectionUtils.isEmpty(pageList)) {
            return PageBuilder.buildPageResult(page,new ArrayList<>());
        }
        List<MessageReplyResp> respList =
            mapperFacade.mapAsList(pageList, MessageReplyResp.class);
        Integer startIndex = (pageReq.getItemsPerPage() * pageReq.getCurrentPage()) - pageReq.getItemsPerPage() + 1;
        AtomicInteger idBeginIndex = new AtomicInteger(startIndex);
            respList.stream().forEach(item -> {
                item.setId(Integer.valueOf(idBeginIndex.getAndIncrement()).longValue());
        });
        return PageBuilder.buildPageResult(page,respList);
    }

    /**
     * 设置分页条件
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/5/31
     * @param pageWrapper 查询条件
     * @param pageReq 分页插件
     * @return
     */
    private void setPageCriteria(LambdaQueryWrapper<MessageReply> pageWrapper, MessageReplyReq pageReq){

         if(!CheckParam.isNull(pageReq.getMessageWordId())){
             pageWrapper.like(MessageReply::getMessageWordId,"%"+pageReq.getMessageWordId());
         }

         if(!CheckParam.isNull(pageReq.getMessageContent())){
             pageWrapper.like(MessageReply::getMessageContent,"%"+pageReq.getMessageContent());
         }
    }

    /**
     * 更新
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/4/2
     * @param updateReq 更新请求参数
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateItem(MessageReplyUpdateReq updateReq){
        log.info(">>>>>>>>>>>>>>>>>更新请求参数 {} <<<<<<<<<<<<<<<<", JSON.toJSONString(updateReq));
        String mainId = updateReq.getMessageReplyId();
        MessageReply result = messageReplyRepository.selectOne(new LambdaQueryWrapper<MessageReply>()
                    .eq(MessageReply::getMessageReplyId,mainId));
        if (CheckParam.isNull(result)) {
            return;
        }
        setNeedUpdateItem(result,updateReq);
        messageReplyRepository.updateById(result);
    }

    /**
     * 设置需要更新的字段
     * @author: create by singer - Singer email:singer-coder@qq.com
     * @date 2021/3/30
     * @param updateReq 更新参数
     * @param entity 产业
     */
    private void setNeedUpdateItem(MessageReply entity,
        MessageReplyUpdateReq updateReq){
        if(!CheckParam.isNull(updateReq.getMessageWordId())){
            entity.setMessageWordId(updateReq.getMessageWordId());
        }
        if(!CheckParam.isNull(updateReq.getMessageContent())){
            entity.setMessageContent(updateReq.getMessageContent());
        }
    }
}
