package com.iformall.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.IdWorker;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.WxActivity;
import com.iformall.domain.po.WxCampaign;
import com.iformall.domain.po.WxCoupon;
import com.iformall.domain.po.WxCouponChannel;
import com.iformall.enums.*;
import com.iformall.mapper.WxActivityMapper;
import com.iformall.mapper.WxCampaignMapper;
import com.iformall.mapper.WxCouponChannelMapper;
import com.iformall.service.QrCodeService;
import com.iformall.service.WxCampaignService;
import com.iformall.service.WxCouponService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class WxCampaignServiceImpl implements WxCampaignService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
    WxCampaignMapper wxCampaignMapper;

    @Autowired
    WxCouponChannelMapper wxCouponChannelMapper;

    @Autowired
    WxCouponService wxCouponService;

    @Autowired
    QrCodeService qrCodeService;

    @Autowired
    WxActivityMapper wxActivityMapper;

    @Override
    public PageInfo<WxCampaign> listAsPage(WxCampaign record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCampaignMapper.findList(record));
    }

    @Override
    public PageInfo<WxCampaign> clistAsPage(WxCampaign record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCampaignMapper.findCList(record));
    }

    @Override
    public WxCampaign getById(Long id) {
        WxCampaign wxCampaign = wxCampaignMapper.selectById(id);
        String html = wxCampaign.getHtml();
        if (!StringUtils.isEmpty(html)) {
            try {
                html = URLDecoder.decode(html, "utf-8");
            } catch (UnsupportedEncodingException e) {
                logger.info("图文内容解码失败");
            }
            wxCampaign.setHtml(html);
        }
        return wxCampaign;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    @Override
    public ResultData saveOrUpdate(WxCampaign wxCampaign) {
        if(wxCampaign.getType().equals(EnumCampaignType.STABLE.getCode())) {
            if (StringUtils.isEmpty(wxCampaign.getCoverImg())) {
                return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "封面图不能为空");
            }
            if (StringUtils.isEmpty(wxCampaign.getTitle())) {
                return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "标题不能为空");
            }
            if (StringUtils.isEmpty(wxCampaign.getDetail())) {
                return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "活动说明不能为空");
            }
        } else if(wxCampaign.getType().equals(EnumCampaignType.FREE.getCode())){
            if (StringUtils.isEmpty(wxCampaign.getHtml())) {
                return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "图文不能为空");
            }
            int length = wxCampaign.getHtml().getBytes().length;
            if (length >= 0xFFFFFF) { //Mysql MiddleText length limited
                return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(), "图文内容过大无法保存");
            }
        } else {
            return new ResultData(ErrorCode.SYS_PARAMETER_ERROR);
        }
        wxCampaign.setStatus(EnumCampaignStatus.STATUS_THROW_IN.getCode());
        if (wxCampaign.getId() == null) {
            final IdWorker idWorker = IdWorker.get();
            wxCampaign.setId(idWorker.nextId());
            wxCampaignMapper.insert(wxCampaign);
        } else {
            wxCampaignMapper.updateById(wxCampaign);
        }
        //type 为固定格式才会有券的信息 才会有投放的问题
        couponInject(wxCampaign);
        return new ResultData(Result.SUCCESS,"操作成功");
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    @Override
    public ResultData addForPath(WxCampaign wxCampaign) {
        if(wxCampaign.getType().equals(EnumCampaignType.PAGEPATH.getCode())) {
            if (StringUtils.isBlank(wxCampaign.getCoverImg())) {
                return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "封面图不能为空");
            }
            if (wxCampaign.getProduceType() == null) {
                return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "produceType不能为空");
            }
            if (wxCampaign.getProduceType().equals(EnumCampaignProductType.ACTIVITY_JOIN.getCode())
                    && wxCampaign.getProduceId() == null) {
                return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "produceId不能为空");
            }
            if (StringUtils.isBlank(wxCampaign.getPagePath())) {
                return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "pagePath不能为空");
            }
        } else {
            return new ResultData(ErrorCode.SYS_PARAMETER_ERROR);
        }
        wxCampaign.setStatus(EnumCampaignStatus.STATUS_THROW_IN.getCode());
        if (wxCampaign.getId() == null) {
            final IdWorker idWorker = IdWorker.get();
            wxCampaign.setId(idWorker.nextId());
            wxCampaignMapper.insert(wxCampaign);
        } else {
            wxCampaignMapper.updateById(wxCampaign);
        }
        //type 为固定格式才会有券的信息 才会有投放的问题
        couponInject(wxCampaign);
        return new ResultData(Result.SUCCESS,"操作成功");
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    @Override
    public ResultData updateStatus(WxCampaign wxCampaign) {
        wxCampaignMapper.updateById(wxCampaign);
        if (wxCampaign.getType().equals(EnumCampaignType.PAGEPATH.getCode())) {
            WxCampaign campaign = wxCampaignMapper.selectById(wxCampaign.getId());
            WxActivity wxActivity = new WxActivity();
            wxActivity.setId(campaign.getProduceId());
            wxActivity.setStatus(wxCampaign.getStatus());
            wxActivity.setUpdateTime(new Date());
            wxActivityMapper.updateById(wxActivity);
        }
        //type 为固定格式才会有券的信息 才会有投放的问题
        couponInject(wxCampaign);
        return new ResultData(Result.SUCCESS, "操作成功");
    }

    public void couponInject(WxCampaign wxCampaign) {
        wxCampaign = wxCampaignMapper.selectById(wxCampaign.getId());
        if (wxCampaign.getType().equals(EnumCampaignType.STABLE.getCode())) {
            if (wxCampaign.getStatus().equals(EnumCampaignStatus.STATUS_THROW_IN.getCode())) {
                addOrUpdateBatch(JSONArray.parseArray(wxCampaign.getCouponIds(), String.class), wxCampaign);
            } else {
                delBatch(wxCampaign);
            }
        }
    }

    public void delBatch(WxCampaign record) {
        // couponChannel 下架
        WxCouponChannel wxCouponChannelQ = new WxCouponChannel();
        wxCouponChannelQ.setTenantId(record.getTenantId());
        wxCouponChannelQ.setTargetAd(EnumCouponChannelType.COUPON_CHANNEL_ID_CAMPAIN.getCode());
        wxCouponChannelQ.setSubTargetId(record.getId());
        wxCouponChannelQ.setStatus(EnumCouponChannelStatus.STATUS_THROW_IN.getCode());
        List<WxCouponChannel> wxCouponChannels = wxCouponChannelMapper.findList(wxCouponChannelQ);
        if (wxCouponChannels.size() > 0) {
            for (WxCouponChannel ch : wxCouponChannels) {
                ch.setStatus(EnumCouponChannelStatus.STATUS_TAKE_OFFF.getCode());
                ch.setUpdateDate(new Date());
                wxCouponChannelMapper.updateById(ch);
            }
        }
    }

    public void addOrUpdateBatch(List<String> ids, WxCampaign record) {
        // 获取已上架的CouponChannel
        WxCouponChannel wxCouponChannelQ = new WxCouponChannel();
        wxCouponChannelQ.setTenantId(record.getTenantId());
        wxCouponChannelQ.setTargetAd(EnumCouponChannelType.COUPON_CHANNEL_ID_CAMPAIN.getCode());
        wxCouponChannelQ.setSubTargetId(record.getId());
        wxCouponChannelQ.setStatus(EnumCouponChannelStatus.STATUS_THROW_IN.getCode());
        List<WxCouponChannel> wxCouponChannels = wxCouponChannelMapper.findList(wxCouponChannelQ);
        Map<Long, WxCouponChannel> wxCouponChannelsMap = new HashMap<Long, WxCouponChannel>();
        for(WxCouponChannel wxCouponChannel: wxCouponChannels) {
            wxCouponChannelsMap.put(wxCouponChannel.getCouponId(), wxCouponChannel);
        }

        // 上架 couponChannel 更新
        for (String couponIdStr:ids) {
            Long couponId = Long.parseLong(couponIdStr);
            saveOrUpdateCouponChannel(couponId, wxCouponChannelsMap, record);
        }

        // 下架更新
        if (!wxCouponChannelsMap.isEmpty()) {
            for (WxCouponChannel wxCouponChannel : wxCouponChannelsMap.values()) {
                wxCouponChannel.setStatus(EnumCouponChannelStatus.STATUS_TAKE_OFFF.getCode());
                wxCouponChannel.setUpdateDate(new Date());
                wxCouponChannelMapper.updateById(wxCouponChannel);
            }
        }
    }

    public void saveOrUpdateCouponChannel(Long couponId, Map<Long, WxCouponChannel> wxCouponChannelsMap, WxCampaign record){

        WxCoupon wxCoupon = wxCouponService.getById(couponId);
        if (wxCoupon == null) {
            return;
        }
        if (wxCoupon.getStatus() != EnumCouponStatus.COUPON_STATUS_THROW_IN.getCode()) {
            return;
        }
        if (wxCoupon.getValidEndDate() != null && wxCoupon.getValidEndDate().before(new Date())) {
            return;
        }

        // 已有的couponChannel, 更新
        WxCouponChannel wxCouponChannel = wxCouponChannelsMap.get(couponId);
        if (wxCouponChannel != null) {
            wxCouponChannel.setStatus(EnumCouponChannelStatus.STATUS_THROW_IN.getCode());
            wxCouponChannel.setBeginTime(record.getValidStartDate());
            wxCouponChannel.setEndTime(record.getValidEndDate());
            wxCouponChannel.setUpdateDate(new Date());
            wxCouponChannelMapper.updateById(wxCouponChannel);
            wxCouponChannelsMap.remove(couponId);
        } else {
            // 不存在的, 新增
            wxCouponChannel = new WxCouponChannel();
            wxCouponChannel.setBeginTime(record.getValidStartDate());
            wxCouponChannel.setEndTime(record.getValidEndDate());
            wxCouponChannel.setStatus(EnumCouponChannelStatus.STATUS_THROW_IN.getCode());
            wxCouponChannel.setCouponId(couponId);
            wxCouponChannel.setType(wxCoupon.getType());
            wxCouponChannel.setTargetAd(EnumCouponChannelType.COUPON_CHANNEL_ID_CAMPAIN.getCode());
            wxCouponChannel.setTenantId(wxCoupon.getTenantId());
            wxCouponChannel.setBusiness(wxCoupon.getBusiness());
            wxCouponChannel.setSubBusiness(wxCoupon.getSubBusiness());
            wxCouponChannel.setTitle(wxCoupon.getTitle());
            wxCouponChannel.setSubTargetId(record.getId());
            final IdWorker idWorker = IdWorker.get();
            wxCouponChannel.setId(idWorker.nextId());
            wxCouponChannelMapper.insert(wxCouponChannel);

            String pageUrl = "pages/index/index";
            WxCouponChannel couponChannel = new WxCouponChannel();
            couponChannel.setId(wxCouponChannel.getId());
            couponChannel.setType(wxCouponChannel.getType());
            String param = couponChannel.getWeappScene();
            ResultData resultDataQ = qrCodeService.uploadQrcode(wxCoupon.getTenantId(),1,pageUrl,param,0,"","","卷");
            Map<String,String> map = (Map)resultDataQ.data;
            if(map!=null && map.get("url") !=null) {
                String url = map.get("url");
                couponChannel.setQrCode(url);
                wxCouponChannelMapper.updateById(couponChannel);
            }
        }
    }

    @Override
    public void deleteById(Long id) {
        wxCampaignMapper.deleteById(id);
    }

    @Override
    public int getMaxSortNum(String tenantId) {
        return wxCampaignMapper.getMaxSortNum(tenantId);
    }

    @Override
    public void printHtmlById(Long id, HttpServletResponse response) {
        try {
            response.setHeader("Content-type","text/html;charset=utf-8");
            WxCampaign wxCampaign = wxCampaignMapper.selectById(id);
            String html = StringUtils.isEmpty(wxCampaign.getHtml()) ? "" : wxCampaign.getHtml();
            try {
                html = URLDecoder.decode(html, "utf-8");
            } catch (UnsupportedEncodingException e) {
                logger.info("图文内容解码失败");
            }
            // 循环取出流中的数据
            byte[] b = new byte[1024];
            int len;
            InputStream inStream = new ByteArrayInputStream(html.getBytes());
            while ((len = inStream.read(b)) > 0){
                response.getOutputStream().write(b, 0, len);
            }
            inStream.close();
        } catch (Exception e) {
            logger.info("输出富文本内容" + e.getMessage());
            e.printStackTrace();
        }
    }


}
