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

import com.google.common.collect.Lists;
import com.pcloud.appcenter.app.dto.AppDto;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.consumer.app.AppConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.group.enums.AppAndProductTypeEnum;
import com.pcloud.book.timecontrol.biz.TaskBiz;
import com.pcloud.book.timecontrol.biz.TaskPrizeBiz;
import com.pcloud.book.timecontrol.dto.ReplyMessageBaseDto;
import com.pcloud.book.timecontrol.entity.TimeControlPrizeItem;
import com.pcloud.book.timecontrol.entity.TimeControlTask;
import com.pcloud.book.timecontrol.entity.TimeControlTaskItem;
import com.pcloud.book.timecontrol.entity.TimeControlTaskPrize;
import com.pcloud.book.timecontrol.enums.TaskPrizeItemTypeEnum;
import com.pcloud.book.timecontrol.enums.TaskPrizeTypeEnum;
import com.pcloud.book.timecontrol.mapper.TaskPrizeItemMapper;
import com.pcloud.book.timecontrol.mapper.TaskPrizeMapper;
import com.pcloud.book.timecontrol.mapper.TimeControlTaskItemMapper;
import com.pcloud.book.timecontrol.mapper.TimeControlTaskMapper;
import com.pcloud.book.timecontrol.vo.CouponVO;
import com.pcloud.book.timecontrol.vo.CreateAppVO;
import com.pcloud.book.timecontrol.vo.CreateCertificateVO;
import com.pcloud.book.timecontrol.vo.CreatePrize4TaskItemVO;
import com.pcloud.book.timecontrol.vo.QueryAppVO;
import com.pcloud.book.timecontrol.vo.QueryCertificateVO;
import com.pcloud.book.timecontrol.vo.QueryCouponVO;
import com.pcloud.book.timecontrol.vo.QueryPrizeVO;
import com.pcloud.book.timecontrol.vo.SaveCertificateVO;
import com.pcloud.book.timecontrol.vo.SaveCouponVO;
import com.pcloud.book.timecontrol.vo.SaveTaskPrizeVO;
import com.pcloud.book.timecontrol.vo.request.AppRequestVO;
import com.pcloud.book.timecontrol.vo.request.CertificateRequestVO;
import com.pcloud.book.timecontrol.vo.request.PrizeCouponRequestVO;
import com.pcloud.book.timecontrol.vo.request.SavePrize4TaskItemVO;
import com.pcloud.book.util.common.YesOrNoEnums;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.entity.UploadResultInfo;
import com.pcloud.common.enums.ImageTypeEnum;
import com.pcloud.common.utils.BeanUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.NumberUtil;
import com.pcloud.common.utils.UUIDUitl;
import com.pcloud.common.utils.aliyun.OssUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.wechatgroup.group.dto.GroupUserDTO;
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 javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Component("taskPrizeBiz")
public class TaskPrizeBizImpl implements TaskPrizeBiz {

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

    @Autowired
    private TimeControlTaskMapper taskMapper;
    @Autowired
    private TimeControlTaskItemMapper taskItemMapper;
    @Autowired
    private TaskPrizeMapper taskPrizeMapper;
    @Autowired
    private TaskPrizeItemMapper taskPrizeItemMapper;
    @Autowired
    private TaskBiz taskBiz;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;

    @ParamLog("保存累计奖励")
    @Transactional(rollbackFor = Exception.class)
    public Integer saveTaskPrize(SaveTaskPrizeVO saveTaskPrizeVO){
        Integer taskId = saveTaskPrizeVO.getTaskId();
        if (null == taskId) {
            throw new BookBizException(BookBizException.ERROR, "taskId不能为空！");
        }
        TimeControlTask timeControlTask = taskMapper.selectByPrimaryKey(taskId);
        if (null == timeControlTask) {
            throw new BookBizException(BookBizException.ERROR, "任务不存在！");
        }

        List<TimeControlPrizeItem> prizeItems = Lists.newArrayList();
        // 构建优惠券对象
        buildCoupon(saveTaskPrizeVO, prizeItems);
        // 构建课程对象
        buildApp(saveTaskPrizeVO, prizeItems);
        // 构建奖状对象
        buildCertificate(saveTaskPrizeVO, prizeItems);

        // 删除旧数据
        taskPrizeMapper.deleteByTaskId(taskId, TaskPrizeTypeEnum.GRAND_TOTAL.key);
        if(NumberUtil.isNumber(saveTaskPrizeVO.getId()) && saveTaskPrizeVO.getId() > 0){
            taskPrizeItemMapper.deleteByPrizeId(saveTaskPrizeVO.getId());
        }
        // 新增
        Integer prizeId = insertTaskPrize(saveTaskPrizeVO);
        if(!ListUtils.isEmpty(prizeItems)){
            prizeItems.stream().forEach(x->{ x.setPrizeId(prizeId); });
            taskPrizeItemMapper.batchInsert(prizeItems);
        }
        return prizeId;
    }

    @ParamLog("累计奖励数据入库")
    private Integer insertTaskPrize(SaveTaskPrizeVO saveTaskPrizeVO) {
        TimeControlTaskPrize timeControlTaskPrize = new TimeControlTaskPrize();
        BeanUtils.copyProperties(saveTaskPrizeVO, timeControlTaskPrize);
        timeControlTaskPrize.setType(TaskPrizeTypeEnum.GRAND_TOTAL.key);
        taskPrizeMapper.insert(timeControlTaskPrize);
        return timeControlTaskPrize.getId();
    }

    @ParamLog("构建优惠券对象")
    private void buildCoupon(SaveTaskPrizeVO saveTaskPrizeVO, List<TimeControlPrizeItem> prizeItems) {
        if(YesOrNoEnums.NO.getValue().equals(saveTaskPrizeVO.getHasCoupon())){
            return;
        }
        SaveCouponVO couponVO = saveTaskPrizeVO.getCouponVO();
        if (StringUtil.isEmpty(couponVO.getCouponTitle()) || StringUtil.isEmpty(couponVO.getCouponUrl())) {
            throw new BookBizException(BookBizException.ERROR, "请填写完整的优惠券信息！");
        }
        TimeControlPrizeItem timeControlPrizeItem = new TimeControlPrizeItem();
        BeanUtils.copyProperties(couponVO, timeControlPrizeItem);
        timeControlPrizeItem.setTaskId(saveTaskPrizeVO.getTaskId());
        timeControlPrizeItem.setPrizeType(TaskPrizeItemTypeEnum.COUPON.key);
        prizeItems.add(timeControlPrizeItem);
    }

    @ParamLog("构建课程对象")
    private void buildApp(SaveTaskPrizeVO saveTaskPrizeVO, List<TimeControlPrizeItem> prizeItems) {
        if(YesOrNoEnums.NO.getValue().equals(saveTaskPrizeVO.getHasApp())){
            return;
        }
        TimeControlPrizeItem timeControlPrizeItem = new TimeControlPrizeItem();
        BeanUtils.copyProperties(saveTaskPrizeVO.getAppVO(), timeControlPrizeItem);
        timeControlPrizeItem.setTaskId(saveTaskPrizeVO.getTaskId());
        timeControlPrizeItem.setPrizeType(TaskPrizeItemTypeEnum.APP.key);
        prizeItems.add(timeControlPrizeItem);
    }

    @ParamLog("构建奖状对象")
    private void buildCertificate(SaveTaskPrizeVO saveTaskPrizeVO, List<TimeControlPrizeItem> prizeItems) {
        if(YesOrNoEnums.NO.getValue().equals(saveTaskPrizeVO.getHasCertificate())){
            return;
        }
        SaveCertificateVO certificateVO = saveTaskPrizeVO.getCertificateVO();
        if (StringUtil.isEmpty(certificateVO.getCertificateTitle()) || StringUtil.isEmpty(certificateVO.getCertificateUser())) {
            throw new BookBizException(BookBizException.ERROR, "请填写完整的奖状信息！");
        }
        TimeControlPrizeItem timeControlPrizeItem = new TimeControlPrizeItem();
        BeanUtils.copyProperties(certificateVO, timeControlPrizeItem);
        timeControlPrizeItem.setTaskId(saveTaskPrizeVO.getTaskId());
        timeControlPrizeItem.setPrizeType(TaskPrizeItemTypeEnum.CERTIFICATE.key);
        prizeItems.add(timeControlPrizeItem);
    }

    @ParamLog("查询累计奖励")
    @Override
    public QueryPrizeVO getPrize4Task(Integer taskId) {
        if (null == taskId) {
            throw new BookBizException(BookBizException.ERROR, "taskId不能为空");
        }
        QueryPrizeVO prizeVO = new QueryPrizeVO();
        TimeControlTaskPrize timeControlTaskPrize = taskPrizeMapper.getByTaskId(taskId, TaskPrizeTypeEnum.GRAND_TOTAL.key);
        if(timeControlTaskPrize == null || timeControlTaskPrize.getId() == 0){
            return prizeVO;
        }
        BeanUtils.copyProperties(timeControlTaskPrize, prizeVO);
        //获取奖励
        this.fillPrizeItem(prizeVO);
        return prizeVO;
    }

    @Override
    @ParamLog(value = "获取单次任务奖励", isAfterReturn = false)
    public QueryPrizeVO getPrize4TaskItem(Integer taskItemId) {
        if (null == taskItemId){
            throw new BookBizException(BookBizException.ERROR, "taskItemId不能为空");
        }
        QueryPrizeVO prizeVO = new QueryPrizeVO();
        TimeControlTaskPrize timeControlTaskPrize = taskPrizeMapper.selectByTaskItemId(taskItemId);
        if (null == timeControlTaskPrize || null == timeControlTaskPrize.getId()){
            return prizeVO;
        }
        BeanUtils.copyProperties(timeControlTaskPrize, prizeVO);
        //获取奖励
        this.fillPrizeItem(prizeVO);
        return prizeVO;
    }

    @Override
    @ParamLog("保存单次任务奖励")
    @Transactional(rollbackFor = Exception.class)
    public void savePrize4TaskItem(SavePrize4TaskItemVO vo) {
        TimeControlTaskPrize timeControlTaskPrize = SavePrize4TaskItemVO.valueToTaskPrize(vo);
        List<TimeControlPrizeItem> prizeItems = new ArrayList<>();
        //要删除的奖励类型
        List<Integer> deleteTypes = new ArrayList<>();
        if (YesOrNoEnums.YES.getValue().equals(vo.getHasCoupon())){
            Optional.ofNullable(vo.getCoupon()).orElseThrow(() -> new BookBizException(BookBizException.ERROR, "未设置优惠券"));
            TimeControlPrizeItem couponPrizeItem = PrizeCouponRequestVO.valueToPrizeItem(vo);
            prizeItems.add(couponPrizeItem);
            deleteTypes.add(couponPrizeItem.getPrizeType());
        }
        if (YesOrNoEnums.YES.getValue().equals(vo.getHasApp())){
            Optional.ofNullable(vo.getApp()).orElseThrow(() -> new BookBizException(BookBizException.ERROR, "未设置课程"));
            TimeControlPrizeItem appPrizeItem = AppRequestVO.valueToPrizeItem(vo);
            prizeItems.add(appPrizeItem);
            deleteTypes.add(appPrizeItem.getPrizeType());
        }
        if (YesOrNoEnums.YES.getValue().equals(vo.getHasCertificate())){
            Optional.ofNullable(vo.getCertificate()).orElseThrow(() -> new BookBizException(BookBizException.ERROR, "未设置证书"));
            TimeControlPrizeItem certificatePrizeItem = CertificateRequestVO.valueToPrizeItem(vo);
            prizeItems.add(certificatePrizeItem);
            deleteTypes.add(certificatePrizeItem.getPrizeType());
        }
        taskPrizeMapper.deleteByTaskItemId(vo.getTaskItemId());
        taskPrizeMapper.insert(timeControlTaskPrize);
        if (deleteTypes.size() == 0){
            return;
        }
        prizeItems = prizeItems.stream().peek(item -> item.setPrizeId(timeControlTaskPrize.getId())).collect(Collectors.toList());
        taskPrizeItemMapper.deleteByTaskItemId(vo.getTaskItemId(), deleteTypes);
        taskPrizeItemMapper.batchInsert(prizeItems);
    }

    @Override
    public String downloadCertificate(Integer id, Integer type) {
        TimeControlTaskPrize taskPrize = taskPrizeMapper.getByType(id, type);
        if (taskPrize == null) {
            throw new BookBizException(BookBizException.ERROR, "保存奖状设置后才可下载");
        }
        List<TimeControlPrizeItem> timeControlPrizeItems = taskPrizeItemMapper.listByPrizeId(taskPrize.getId());
        if (!ListUtils.isEmpty(timeControlPrizeItems)) {
            for (TimeControlPrizeItem timeControlPrizeItem : timeControlPrizeItems) {
                if (timeControlPrizeItem.getPrizeType().equals(TaskPrizeItemTypeEnum.CERTIFICATE.key)) {
                    return downloadUrl(timeControlPrizeItem, null);
                }
            }
        }
        throw new BookBizException(BookBizException.ERROR, "保存奖状设置后才可下载");
    }

    public String downloadUrl(TimeControlPrizeItem timeControlPrizeItem, String wxUserId) {
        //发送奖状
        String fFileUrl = timeControlPrizeItem.getCertificateBaseUrl();
        fFileUrl = fFileUrl.replace("//oss.", "//file.");
        try {
            //准备画板
            BufferedImage bg;
            bg = ImageIO.read(new URL(fFileUrl));
            BufferedImage bg1 = new BufferedImage(bg.getWidth(), bg.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
            Graphics2D g = bg1.createGraphics();
            g.drawImage(bg.getScaledInstance(bg.getWidth(), bg.getHeight(), Image.SCALE_DEFAULT), 0, 0, null);
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            String name = "xxx";
            if (null != wxUserId) {
                GroupUserDTO wxUserInfoByWxUserId = wechatGroupConsr.getWxUserInfoByWxUserId(wxUserId);
                name = wxUserInfoByWxUserId.getNickName();
            }
            //绘制昵称
            name = "亲爱的" + name + ":";
            g.setColor(new Color(102, 102, 102));
            Font font = new Font("黑体", Font.BOLD, 16);
            g.setFont(font);
            g.drawString(name, 23, 85);
            //绘制文案
            String certificateTitle = timeControlPrizeItem.getCertificateTitle();
            int length = certificateTitle.length();

            if (length > 33) {
                g.drawString(timeControlPrizeItem.getCertificateTitle().substring(0, 16), 40, 115);
                g.drawString(timeControlPrizeItem.getCertificateTitle().substring(16, 33), 23, 138);
                g.drawString(timeControlPrizeItem.getCertificateTitle().substring(33), 23, 161);
            } else if (length > 16) {
                g.drawString(timeControlPrizeItem.getCertificateTitle().substring(0, 16), 40, 115);
                g.drawString(timeControlPrizeItem.getCertificateTitle().substring(16), 23, 138);
            } else {
                g.drawString(timeControlPrizeItem.getCertificateTitle(), 40, 115);
            }
            //绘制日期
            Calendar cal = Calendar.getInstance();
            cal.setTime(new Date());
            Integer year = cal.get(Calendar.YEAR);
            Integer month = cal.get(Calendar.MONTH) + 1;
            Integer day = cal.get(Calendar.DATE);
            g.drawString(year + "年" + month + "月" + day + "日", 180, 215);

            //绘制落款
            String loan = timeControlPrizeItem.getCertificateUser();
            g.setColor(new Color(102, 102, 102));
            g.setFont(font);
            FontMetrics fm = g.getFontMetrics(font);
            int textWidth = fm.stringWidth(loan);
            int x = bg.getWidth() - textWidth - 20;
            g.drawString(loan, x, 190);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(bg1, ImageTypeEnum.JPG.value, os);
            UploadResultInfo uploadResultInfo = OssUtils.uploadFileByte(os.toByteArray(), UUIDUitl.taskName(), ImageTypeEnum.JPG.value);
            os.close();

            String url = uploadResultInfo == null ? null : uploadResultInfo.getUrl();
            LOGGER.info("上传后的地址:" + url);
            if (url != null) {
                url = url.replace("//oss.", "//file.");
                return url;
            }
        } catch (Exception e) {
            LOGGER.error("生成奖状失败：" + e.getMessage(), e);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createPrize4TaskItem(CreatePrize4TaskItemVO createPrize4TaskItemVO) {
        Integer taskItemId = createPrize4TaskItemVO.getTaskItemId();
        TimeControlTaskItem timeControlTaskItem = taskItemMapper.selectByPrimaryKey(taskItemId);
        if (null == timeControlTaskItem) {
            throw new BookBizException(BookBizException.ERROR, "任务不存在！");
        }
        Integer taskId = timeControlTaskItem.getTaskId();
        TimeControlTask timeControlTask = taskMapper.selectByPrimaryKey(taskId);
        if (null == timeControlTask) {
            throw new BookBizException(BookBizException.ERROR, "任务不存在！");
        }
        List<TimeControlPrizeItem> prizeItemList = new ArrayList<>();
        //参数校验
        if (YesOrNoEnums.YES.getValue().equals(createPrize4TaskItemVO.getHasCoupon())) {
            CouponVO couponVO = createPrize4TaskItemVO.getCouponVO();
            if (StringUtil.isEmpty(couponVO.getCouponTitle()) || StringUtil.isEmpty(couponVO.getCouponUrl())) {
                throw new BookBizException(BookBizException.ERROR, "请填写完整的优惠券信息！");
            }
            TimeControlPrizeItem prizeItem = new TimeControlPrizeItem();
            BeanUtils.copyProperties(couponVO, prizeItem);
            prizeItem.setPrizeType(TaskPrizeItemTypeEnum.COUPON.key);
            prizeItemList.add(prizeItem);
        }
        if (YesOrNoEnums.YES.getValue().equals(createPrize4TaskItemVO.getHasCertificate())) {
            CreateCertificateVO createCertificateVO = createPrize4TaskItemVO.getCreateCertificateVO();
            if (StringUtil.isEmpty(createCertificateVO.getCertificateTitle()) || StringUtil.isEmpty(createCertificateVO.getCertificateUser())) {
                throw new BookBizException(BookBizException.ERROR, "请填写完整的奖状信息！");
            }
            TimeControlPrizeItem prizeItem = new TimeControlPrizeItem();
            BeanUtils.copyProperties(createCertificateVO, prizeItem);
            prizeItem.setPrizeType(TaskPrizeItemTypeEnum.CERTIFICATE.key);
            prizeItemList.add(prizeItem);
        }
        if (YesOrNoEnums.YES.getValue().equals(createPrize4TaskItemVO.getHasApp())) {
            CreateAppVO createAppVO = createPrize4TaskItemVO.getCreateAppVO();
            TimeControlPrizeItem prizeItem = new TimeControlPrizeItem();
            BeanUtils.copyProperties(createAppVO, prizeItem);
            prizeItem.setPrizeType(TaskPrizeItemTypeEnum.APP.key);
            prizeItemList.add(prizeItem);
        }
        TimeControlTaskPrize taskPrize = TimeControlTaskPrize.builder().taskId(taskId).taskItemId(taskItemId).type(TaskPrizeTypeEnum.SINGLE.key)
                .totalPrizeNum(0).hasCoupon(createPrize4TaskItemVO.getHasCoupon()).hasApp(createPrize4TaskItemVO.getHasApp())
                .hasCertificate(createPrize4TaskItemVO.getHasCertificate()).build();
        taskPrizeMapper.insert(taskPrize);
        Integer prizeId = taskPrize.getId();
        if (!ListUtils.isEmpty(prizeItemList)) {
            prizeItemList.forEach(timeControlPrizeItem -> {
                timeControlPrizeItem.setTaskId(taskId);
                timeControlPrizeItem.setTaskItemId(taskItemId);
                timeControlPrizeItem.setPrizeId(prizeId);
            });
        }
        taskPrizeItemMapper.batchInsert(prizeItemList);
        return prizeId;
    }

    @ParamLog("填充任务奖励item")
    private void fillPrizeItem(QueryPrizeVO prizeVO){
        List<TimeControlPrizeItem> prizeItems = taskPrizeItemMapper.listByPrizeId(prizeVO.getId());
        if(ListUtils.isEmpty(prizeItems)){
            return;
        }
        for (TimeControlPrizeItem prizeItem : prizeItems){
            if (TaskPrizeItemTypeEnum.COUPON.key.equals(prizeItem.getPrizeType())){
                QueryCouponVO queryCouponVO = new QueryCouponVO();
                BeanUtils.copyProperties(prizeItem, queryCouponVO);
                prizeVO.setQueryCouponVO(queryCouponVO);
            }else if (TaskPrizeItemTypeEnum.APP.key.equals(prizeItem.getPrizeType())){
                QueryAppVO queryAppVO = new QueryAppVO();
                BeanUtils.copyProperties(prizeItem, queryAppVO);
                fillApp(queryAppVO);
                prizeVO.setQueryAppVO(queryAppVO);
            }else if (TaskPrizeItemTypeEnum.CERTIFICATE.key.equals(prizeItem.getPrizeType())){
                QueryCertificateVO queryCertificateVO = new QueryCertificateVO();
                BeanUtils.copyProperties(prizeItem, queryCertificateVO);
                prizeVO.setQueryCertificateVO(queryCertificateVO);
            }
        }
    }

    @ParamLog("填充APP详情")
    private void fillApp(QueryAppVO queryAppVO) {
        if (NumberUtil.isNumber(queryAppVO.getServeId()) && queryAppVO.getServeId() > 0 && AppAndProductTypeEnum.APP.value.equals(queryAppVO.getServeType())){
            AppDto appDto = appConsr.getBaseById(queryAppVO.getServeId());
            if (appDto!=null){
                queryAppVO.setServePic(appDto.getSquareImg());
                queryAppVO.setServeName(appDto.getTitle());
                queryAppVO.setServeTypeCode(appDto.getTypeCode());
                queryAppVO.setServeTypeName(appDto.getTypeName());
            }
        }
    }

    @Override
    public List<ReplyMessageBaseDto> listTaskItemPrize(Integer taskId) {
        List<ReplyMessageBaseDto> list = taskBiz.listTaskItemDay(taskId);
        if(ListUtils.isEmpty(list)){
            return new ArrayList<>();
        }
        fillConfigState(list);
        return list;
    }

    @ParamLog("填充是否可配置")
    private void fillConfigState(List<ReplyMessageBaseDto> list) {
        List<Integer> taskItemIds = list.stream().filter(a -> a.getConfigState() == 2).map(a -> a.getId()).distinct().collect(Collectors.toList());
        //在配置表的
        List<Integer> configItemId = taskPrizeMapper.getConfigItemId(taskItemIds);
        //在配置表但是开关都是关闭的
        if(!ListUtils.isEmpty(configItemId)){
            List<Integer> allCloseItemId = taskPrizeMapper.getAllCloseItemId(configItemId);
            if(!ListUtils.isEmpty(allCloseItemId)){
                configItemId.removeAll(allCloseItemId);
            }
            for (ReplyMessageBaseDto replyMessageBaseDto : list) {
                if(!ListUtils.isEmpty(configItemId)){
                    if(replyMessageBaseDto.getConfigState()==2 && configItemId.contains(replyMessageBaseDto.getId())){
                        replyMessageBaseDto.setConfigState(1);
                    }
                }

            }
        }
    }

}
