package com.iformall.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.ResultData;
import com.iformall.domain.po.WxCoupon;
import com.iformall.domain.po.WxCouponChannel;
import com.iformall.domain.po.WxCouponMerchant;
import com.iformall.domain.po.WxScreenAd;
import com.iformall.domain.vo.WxCouponCVo;
import com.iformall.domain.vo.WxMerchantVo;
import com.iformall.enums.*;
import com.iformall.mapper.WxCouponChannelMapper;
import com.iformall.mapper.WxCouponMapper;
import com.iformall.mapper.WxCouponMerchantMapper;
import com.iformall.mapper.WxMerchantMapper;
import com.iformall.service.*;
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 com.iformall.common.IdWorker;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;


@Service
public class WxCouponServiceImpl implements WxCouponService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxCouponMapper wxCouponMapper;

    @Autowired
    WxCouponMerchantMapper wxCouponMerchantMapper;

    @Autowired
    WxMerchantMapper wxMerchantMapper;

    @Autowired
    WxCouponChannelService wxCouponChannelService;

    @Autowired
    WxCouponSendService wxCouponSendService;

    @Autowired
    WxOrderService wxOrderService;

    @Autowired
    WxScreenAdService wxScreenAdService;


    @Autowired
    WxCouponChannelMapper wxCouponChannelMapper;


    public ResultData listType(WxCoupon wxCoupon, Integer pageNum, Integer pageSize, Integer type) {
        if (null == wxCoupon) wxCoupon = new WxCoupon();
        wxCoupon.setSortColumns(WxCoupon.Field.Id_DESC);
        PageInfo<WxCoupon> page = null;
        if (wxCoupon.getStatus() != null && wxCoupon.getStatus() == -1)
            wxCoupon.setStatus(null);
        page = listAsPage(wxCoupon, pageNum, pageSize, type);

        List<WxCoupon> wxCouponList = page.getList();

        if (wxCouponList.isEmpty()) {
            return new ResultData(page);
        }

        List<Long> ids = wxCouponList.stream().map(p -> p.getId()).collect(Collectors.toList());
        WxCouponChannel wxCouponChannel = new WxCouponChannel();
        wxCouponChannel.setTenantId(wxCoupon.getTenantId());
        wxCouponChannel.setCouponIds(ids);
        wxCouponChannel.setStatus(EnumCouponChannelStatus.STATUS_THROW_IN.getCode());
        //上架状态
        List<WxCouponChannel> list = wxCouponChannelMapper.findList(wxCouponChannel);
        if (!list.isEmpty()) {
            Map<Long, List<WxCouponChannel>> groupBy = list.stream().collect(Collectors.groupingBy(WxCouponChannel::getCouponId));
            for (WxCoupon temp : wxCouponList) {

                if (groupBy.get(temp.getId()) != null) {
                    List<Integer> channels = new ArrayList<>();
                    for (WxCouponChannel tempchannel : groupBy.get(temp.getId())) {
                        if (!channels.contains(tempchannel.getTargetAd())) {
                            channels.add(tempchannel.getTargetAd());
                        }
                    }
                    String sss = JSON.toJSONString(channels);
                    temp.setChannels(sss);
                } else {
                    temp.setChannels("");
                }

            }
        } else {
            for (WxCoupon temp : wxCouponList) {
                temp.setChannels("");
            }

        }
        return new ResultData(page);
    }



    @Override
    public PageInfo<WxCoupon> listAsPage(WxCoupon record, Integer pageIndex, Integer pageSize, Integer type) {
        if (type == null) {
            return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCouponMapper.findList(record));
        } else if (type.equals(EnumCouponType.CARD_MULTIMCH.getCode())) {
            return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCouponMapper.findCardList(record));
        } else if (type.equals(EnumCouponType.COUPON_PRESS.getCode())) {
            return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCouponMapper.findPressList(record));
        } else {
            return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCouponMapper.findCouponList(record));
        }
    }

    @Override
    public List<WxCoupon> list(WxCoupon record) {
        return wxCouponMapper.findList(record);
    }

    @Override
    public PageInfo<WxCoupon> findCountData(WxCoupon record,Integer pageNum, Integer pageSize) {
        return PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(() -> wxCouponMapper.findCountData(record));
    }

    @Override
    public WxCoupon getById(Long id) {
        return wxCouponMapper.selectByPrimaryKey(id);
    }

    @Override
    public WxCouponCVo getVoById(Long id) {
        WxCouponCVo wxCouponCVo = wxCouponMapper.findVoDetail(id);
        List<WxMerchantVo> merchantList = wxCouponCVo.getMerchantVoList();
        if (merchantList != null) {
            merchantList = merchantList.stream().filter(
                    m->m.getMerchantStatus().equals(EnumMerchantStatus.VALID.getCode()))
                    .collect(Collectors.toList());
        }
        wxCouponCVo.setMerchantVoList(merchantList);
        return wxCouponCVo;
    }


    private Long parseMerchantId(JSONObject merchantParam){
        return Long.valueOf(merchantParam.getString("id"));
    }
    private String parseParameter(JSONObject merchantParam){
        return merchantParam.getString("parameter");
    }
    private Integer parseBusiness(JSONObject merchantParam){
        return Integer.valueOf(merchantParam.getString("businessId"));
    }

    @Override
    @Transactional(isolation=Isolation.SERIALIZABLE, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public ResultData saveOrUpdate(WxCoupon record) {

        if (StringUtils.isNotEmpty(record.getSalePriceStr())) {
            record.setSalePrice((int) (Double.parseDouble(record.getSalePriceStr()) * 100));
        }
        if (StringUtils.isNotEmpty(record.getUsePriceStr())) {
            record.setUsePrice((int) (Double.parseDouble(record.getUsePriceStr()) * 100));
        }
        if (StringUtils.isNotEmpty(record.getPriceStr())) {
            record.setPrice((int) (Double.parseDouble(record.getPriceStr()) * 100));
        }
        if (StringUtils.isNotEmpty(record.getSubsidyNumStr())) {
            record.setSubsidyNum((int) (Double.parseDouble(record.getSubsidyNumStr()) * 100));
        }

        if (record.getValidType() != null) {
            if (record.getValidType().equals(EnumCouponValidType.DAYS_AFTER_RECEIVING.getCode())) {
                record.setValidStartDate(null);
                record.setValidEndDate(null);
            } else if (record.getValidType().equals(EnumCouponValidType.BETWEEN_TWO_TIME.getCode())) {
                record.setValidDays(null);
            } else {
                return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(), "请填写有效时间类型");
            }
        }

        final IdWorker idWorker = IdWorker.get();

        if (record.getId() == null) {

            // check 卡券补贴设置
            if(record.getType().equals(EnumCouponType.COUPON_MULTIMCH.getCode()) ||
                    record.getType().equals(EnumCouponType.CARD_MULTIMCH.getCode())) {
                Integer subsidyType = record.getSubsidyType();
                Integer subsidyNum = record.getSubsidyNum();
                if(subsidyType == null) {
                    return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(), "请填写补贴类型");
                }
                if(subsidyNum == null) {
                    return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(), "请填写补贴金额");
                }
                if(subsidyType.equals(EnumCouponSubsidyType.WECHAT_COUPON.getCode())) {
                    // 微信 立减
                    if(subsidyNum > record.getSalePrice()) {
                        return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "补贴额大于售价");
                    }
                } else if(subsidyType.equals(EnumCouponSubsidyType.OFFLINE_SUBSIDY.getCode())) {
                    // 线下补贴
                    int subsidy_num = record.getPrice() - record.getSalePrice();
                    if(subsidyNum > subsidy_num) {
                        return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "补贴额大于面额与售价的差值");
                    }
                } else if(subsidyType.equals(EnumCouponSubsidyType.WECHAT_MCHPAY.getCode())) {
                    // TODO 微信转账到银行卡

                }
            }

            record.setId(idWorker.nextId());
            if (record.getMerchantParams() != null) {
                List<JSONObject> merchantParamList = JSONObject.parseArray(record.getMerchantParams(), JSONObject.class);
                List<Integer> businessList= new ArrayList<>();
                merchantParamList.forEach(merchantParam -> {
                    WxCouponMerchant cm = new WxCouponMerchant();
                    cm.setId(idWorker.nextId());
                    cm.setMerchantId(parseMerchantId(merchantParam));
                    cm.setParameter(parseParameter(merchantParam));
                    cm.setProductId(record.getId());
                    cm.setCreateDate(new Date());
                    cm.setUpdateDate(new Date());
                    cm.setStatus(EnumCouponMerchantStatus.COUPON_MERCHANT_STATUS_VALID.getCode());
                    businessList.add(parseBusiness(merchantParam));
                    wxCouponMerchantMapper.insertSelective(cm);
                });
                if (businessList.stream().distinct().count() > 1) {
                    record.setBusiness(EnumBusiness.BUSINESS_ID6.getCode());
                } else {
                    record.setBusiness(businessList.get(0));
                }

            } else{
                return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
            }

            record.setCreateDate(new Date());
            record.setUpdateDate(new Date());
            wxCouponMapper.insertSelective(record);

        } else {
            if (record.getMerchantParams() != null) {
                List<JSONObject> merchantParamList = JSONObject.parseArray(record.getMerchantParams(), JSONObject.class);

                WxCouponMerchant cmParam = new WxCouponMerchant();
                cmParam.setProductId(record.getId());
                List<WxCouponMerchant> oldList = wxCouponMerchantMapper.findList(cmParam);
                List<Integer> businessList= new ArrayList<>();
                merchantParamList.stream().forEach(merchantParam -> {
                    WxCouponMerchant cm = new WxCouponMerchant();
                    cm.setMerchantId(parseMerchantId(merchantParam));
                    cm.setProductId(record.getId());
                    WxCouponMerchant rcm = wxCouponMerchantMapper.selectOne(cm);
                    if (rcm != null) {
                        rcm.setMerchantId(Long.valueOf(parseMerchantId(merchantParam)));
                        rcm.setParameter(parseParameter(merchantParam));
                        rcm.setStatus(EnumCouponMerchantStatus.COUPON_MERCHANT_STATUS_VALID.getCode());
                        rcm.setUpdateDate(new Date());
                        wxCouponMerchantMapper.updateByPrimaryKeySelective(rcm);
                    }else {
                        cm.setId(idWorker.nextId());
                        cm.setStatus(EnumCouponMerchantStatus.COUPON_MERCHANT_STATUS_VALID.getCode());
                        cm.setParameter(parseParameter(merchantParam));
                        cm.setCreateDate(new Date());
                        cm.setUpdateDate(new Date());
                        wxCouponMerchantMapper.insertSelective(cm);
                    }
                    businessList.add(Integer.valueOf(parseBusiness(merchantParam)));
                    oldList.removeIf(
                            old->old.getProductId().equals(record.getId()) &&
                             old.getMerchantId().equals(Long.valueOf(parseMerchantId(merchantParam))));
                });

                oldList.stream().forEach(old->{
                    old.setStatus(EnumCouponMerchantStatus.COUPON_MERCHANT_STATUS_INVALID.getCode());
                    old.setUpdateDate(new Date());
                    wxCouponMerchantMapper.updateByPrimaryKeySelective(old);
                });

                if (businessList.stream().distinct().count() > 1) {
                    record.setBusiness(EnumBusiness.BUSINESS_ID6.getCode());
                } else {
                    record.setBusiness(businessList.get(0));
                }
            }

            if (record.getStatus() != null &&
                    (record.getStatus().equals(EnumCouponStatus.COUPON_STATUS_TAKE_OFFF.getCode()))) {

                //下架所有投放频道
                wxCouponChannelService
                        .updateStatusByCouponId(record.getId(), record.getTenantId(), EnumCouponChannelStatus.STATUS_TAKE_OFFF.getCode());
                wxCouponSendService
                        .updateStatusByCouponId(record.getId(), record.getTenantId(), EnumCouponSendStatus.INVALID.getCode());
                //下架所有已砍价券
                wxOrderService.updateStatusByPressCouponId(record.getId(), record.getTenantId(), EnumOrderStatus.ORDER_STATUS_PRESS_CANCEL.getCode());
                //下架所有相关广告
                wxScreenAdService.updateStatusByCouponId(record.getId(), record.getTenantId(), EnumScreenAdStatus.INVALID.getCode());
            }
            record.setUpdateDate(new Date());
            wxCouponMapper.updateByPrimaryKeySelective(record);
        }
        return new ResultData(record.getId());
    }

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

    @Override
    public List<WxCoupon> findSaleMoneyByDate(WxCoupon wxCoupon) {
        return wxCouponMapper.findSaleMoneyByDate(wxCoupon);
    }

    @Override
    public List<WxCoupon> findPaymentByDate(WxCoupon wxCoupon) {
        return wxCouponMapper.findPaymentByDate(wxCoupon);
    }

    @Override
    public Long findSaleCardCount(WxCoupon wxCoupon) {
        Long count = wxCouponMapper.findSaleCardCount(wxCoupon);
        return (count==null)?0l:count;
    }

    @Override
    public Long findTranCardCount(WxCoupon wxCoupon) {
        Long count = wxCouponMapper.findTranCardCount(wxCoupon);
        return (count==null)?0l:count;
    }

    @Override
    public String findSubsidyMoney(WxCoupon wxCoupon) {
        String count = wxCouponMapper.findSubsidyMoney(wxCoupon);
        return (count==null)?"0":count;
    }

    @Override
    public PageInfo<WxCoupon> findCouponData(WxCoupon record, Integer pageNum, Integer pageSize) {
        return PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(() -> wxCouponMapper.findCouponData(record));
    }

    @Override
    public List<WxCoupon> findCouponOrderCount(WxCoupon wxCoupon) {
        return wxCouponMapper.findCouponOrderCount(wxCoupon);
    }


    @Override
    public List<WxCoupon> findCouponPaymentCount(WxCoupon wxCoupon) {
        return wxCouponMapper.findCouponPaymentCount(wxCoupon);
    }

    @Override
    public List<WxCoupon> priceCouponSaleCount(WxCoupon wxCoupon) {
        return wxCouponMapper.priceCouponSaleCount(wxCoupon);
    }

    @Override
    public List<WxCoupon> priceCouponPaymentCount(WxCoupon wxCoupon) {
        return wxCouponMapper.priceCouponPaymentCount(wxCoupon);
    }

    @Override
    public String findSumPriceSaleMoney(WxCoupon wxCoupon) {
        String count = wxCouponMapper.findSumPriceSaleMoney(wxCoupon);
        return (count==null)?"0":count;
    }

    @Override
    public String findSumPricePayMent(WxCoupon wxCoupon) {
        String count = wxCouponMapper.findSumPricePayMent(wxCoupon);
        return (count==null)?"0":count;
    }

    @Override
    public String findSumSubsidyMoney(WxCoupon wxCoupon) {
        String count = wxCouponMapper.findSumSubsidyMoney(wxCoupon);
        return (count==null)?"0":count;
    }

    @Override
    public PageInfo<WxCoupon> findPressData(WxCoupon record, Integer pageNum, Integer pageSize) {
        return PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(() -> wxCouponMapper.findPressData(record));
    }

    @Override
    public List<WxCoupon> pressSendHistory(WxCoupon wxCoupon) {
        return wxCouponMapper.pressSendHistory(wxCoupon);
    }

    @Override
    public List<WxCoupon> pressSuccHistory(WxCoupon wxCoupon) {
        return wxCouponMapper.pressSuccHistory(wxCoupon);
    }

    @Override
    public List<WxCoupon> pressPaymentHistory(WxCoupon wxCoupon) {
        return wxCouponMapper.pressPaymentHistory(wxCoupon);
    }

    @Override
    public String pressSuccRate(WxCoupon wxCoupon) {
        String count = wxCouponMapper.pressSuccRate(wxCoupon);
        if ("0.00".equals(count)) {
            return  "0%";
        } else {
            return count + "%";
        }
    }

    @Override
    public Long sumJoin(WxCoupon wxCoupon) {
        Long count = wxCouponMapper.sumJoin(wxCoupon);
        return (count==null)?0l:count;
    }
}
