package com.liquidnet.service.candy.util;

import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.candy.dto.CandyCouponInfoDto;
import com.liquidnet.service.candy.dto.CandyCouponRuleDto;
import com.liquidnet.service.candy.dto.CandyUserCouponBasicDto;
import com.liquidnet.service.candy.vo.CandyCouponRulesVo;
import com.liquidnet.service.candy.vo.CandyCouponVo;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CouponBaseUtil {


    /**
     * 获取 基础券vo
     *
     * @param dtoItem CandyUserCouponBasicDto
     * @return
     */
    public static CandyCouponVo getBaseCouponUserVo(CandyUserCouponBasicDto dtoItem) {
        LocalDateTime now = LocalDateTime.now();
        CandyCouponVo vo = CandyCouponVo.getNew();
        List<CandyCouponRulesVo> rulesVoList = ObjectUtil.getCandyCouponRulesVos();
        vo.setTitle(dtoItem.getTitle());
        vo.setExpireAt(DateUtil.format(dtoItem.getDuedAt(), DateUtil.Formatter.yyyy_MM_dd));
        vo.setDiscount(dtoItem.getDiscount());
        vo.setValFace(dtoItem.getValFace());
        vo.setBusiType(dtoItem.getBusiType());
        vo.setValOver(dtoItem.getValOver());
        vo.setValMinus(dtoItem.getValMinus());
        vo.setBindType(dtoItem.getBindType());
        vo.setLabel(dtoItem.getLabel());
        vo.setNotice(dtoItem.getNotice());
        vo.setUcouponId(dtoItem.getUcouponId());
        vo.setUsedAt(DateUtil.format(dtoItem.getUsedAt(), DateUtil.Formatter.yyyy_MM_dd));
        vo.setUsedFor(dtoItem.getUsedFor());
        //适用范围 规则
        if (dtoItem.getUseRules() != null) {
            for (CandyCouponRuleDto ruleItem : dtoItem.getUseRules()) {
                CandyCouponRulesVo voRules = CandyCouponRulesVo.getNew();
                voRules.setUseScope(ruleItem.getUseScope());
                voRules.setBusiId(ruleItem.getBusiId());
                voRules.setBusiName(ruleItem.getBusiName());
                rulesVoList.add(voRules);
            }
        }
        //券类别
        if (dtoItem.getBusiType().equals(3)) {
            vo.setCouType(101);
        } else {
            vo.setCouType(dtoItem.getCouType());
        }
        if (dtoItem.getDuedAt() == null) {
            return null;
        }
        vo.setState(getCouponState(now, dtoItem.getDuedAt(), dtoItem.getBindAt(), dtoItem.getState()));
        vo.setUseRules(rulesVoList);
        return vo;
    }

    /**
     * 获取 演出维度 券列表
     *
     * @param dtoItem CandyUserCouponBasicDto
     * @return
     */
    public static CandyCouponVo getPerformanceCouponUserVo(CandyUserCouponBasicDto dtoItem,
                                                           BigDecimal priceTotal,
                                                           String performanceId,
                                                           String timeId,
                                                           String ticketId) {
        boolean isTarget = false;
        LocalDateTime now = LocalDateTime.now();
        CandyCouponVo vo = CandyCouponVo.getNew();
        List<CandyCouponRulesVo> rulesVoList = ObjectUtil.getCandyCouponRulesVos();
        vo.setTitle(dtoItem.getTitle());
        vo.setExpireAt(DateUtil.format(dtoItem.getDuedAt(), DateUtil.Formatter.yyyy_MM_dd));
        vo.setValFace(dtoItem.getValFace());
        vo.setDiscount(dtoItem.getDiscount());
        vo.setValOver(dtoItem.getValOver());
        vo.setValMinus(dtoItem.getValMinus());
        vo.setBindType(dtoItem.getBindType());
        vo.setLabel(dtoItem.getLabel());
        vo.setNotice(dtoItem.getNotice());
        vo.setUcouponId(dtoItem.getUcouponId());
        vo.setUsedAt(DateUtil.format(dtoItem.getUsedAt(), DateUtil.Formatter.yyyy_MM_dd));
        vo.setUsedFor(dtoItem.getUsedFor());
        vo.setBusiType(dtoItem.getBusiType());
        //适用范围 规则
        if (dtoItem.getBusiType().equals(0)) {
            isTarget = true;
        } else if (dtoItem.getBusiType().equals(2)) {
            isTarget = false;
        } else {
            for (CandyCouponRuleDto ruleItem : dtoItem.getUseRules()) {
                CandyCouponRulesVo voRules = CandyCouponRulesVo.getNew();
                voRules.setUseScope(ruleItem.getUseScope());
                voRules.setBusiId(ruleItem.getBusiId());
                voRules.setBusiName(ruleItem.getBusiName());
                rulesVoList.add(voRules);
                switch (ruleItem.getUseScope()) {
                    case 90://演出
                        isTarget = isTargetCoupon(ruleItem.getBusiId(), dtoItem.getCouType(), performanceId, priceTotal, dtoItem.getValOver());
                        break;
                    case 91://场次
                        isTarget = isTargetCoupon(ruleItem.getBusiId(), dtoItem.getCouType(), timeId, priceTotal, dtoItem.getValOver());
                        break;
                    case 92://票
                        isTarget = isTargetCoupon(ruleItem.getBusiId(), dtoItem.getCouType(), ticketId, priceTotal, dtoItem.getValOver());
                        break;
                    case 100://全场
                        if (dtoItem.getCouType().equals(2)) {
                            if (priceTotal.compareTo(dtoItem.getValOver()) >= 0) {
                                isTarget = true;
                            } else {
                                isTarget = false;
                            }
                        } else {
                            isTarget = true;
                        }
                        break;
                    default:
                        isTarget = false;
                        break;
                }
                if (dtoItem.getUseRules().size() > 1 && dtoItem.getCouType().equals(4)) {
                    isTarget = false;
                }
            }

            if (dtoItem.getUseRules().size() == 0 && !dtoItem.getBusiType().equals(0)) {
                isTarget = false;
            }
        }
        //券类别
        if (dtoItem.getBusiType().equals(3)) {
            vo.setCouType(101);
        } else {
            vo.setCouType(dtoItem.getCouType());
        }
        int state = getCouponState(now, dtoItem.getDuedAt(), dtoItem.getBindAt(), dtoItem.getState());
        if (isTarget) {
            vo.setState(state);
        } else {
            vo.setState(state == 1 ? 21 : state);//不在目标范围 如果可用改为不可用21
        }
        vo.setUseRules(rulesVoList);
        return vo;
    }

    /**
     * 获取 商品维度 券列表
     *
     * @param dtoItem CandyUserCouponBasicDto
     * @return
     */
    public static CandyCouponVo getGoodCouponUserVo(CandyUserCouponBasicDto dtoItem,
                                                    BigDecimal priceTotal,
                                                    String goodId,
                                                    Integer size) {
        boolean isTarget = false;
        LocalDateTime now = LocalDateTime.now();
        CandyCouponVo vo = CandyCouponVo.getNew();
        List<CandyCouponRulesVo> rulesVoList = ObjectUtil.getCandyCouponRulesVos();
        vo.setTitle(dtoItem.getTitle());
        vo.setExpireAt(DateUtil.format(dtoItem.getDuedAt(), DateUtil.Formatter.yyyy_MM_dd));
        vo.setValFace(dtoItem.getValFace());
        vo.setValOver(dtoItem.getValOver());
        vo.setDiscount(dtoItem.getDiscount());
        vo.setValMinus(dtoItem.getValMinus());
        vo.setBindType(dtoItem.getBindType());
        vo.setLabel(dtoItem.getLabel());
        vo.setNotice(dtoItem.getNotice());
        vo.setUcouponId(dtoItem.getUcouponId());
        vo.setUsedAt(DateUtil.format(dtoItem.getUsedAt(), DateUtil.Formatter.yyyy_MM_dd));
        vo.setUsedFor(dtoItem.getUsedFor());
        vo.setBusiType(dtoItem.getBusiType());
        //适用范围 规则
        if (dtoItem.getBusiType().equals(0)) {
            isTarget = true;
        } else if (dtoItem.getBusiType().equals(1) || dtoItem.getBusiType().equals(3)) {
            isTarget = false;
        } else {
            for (CandyCouponRuleDto ruleItem : dtoItem.getUseRules()) {
                CandyCouponRulesVo voRules = CandyCouponRulesVo.getNew();
                voRules.setUseScope(ruleItem.getUseScope());
                voRules.setBusiId(ruleItem.getBusiId());
                voRules.setBusiName(ruleItem.getBusiName());
                rulesVoList.add(voRules);
                switch (ruleItem.getUseScope()) {
                    case 80://商品
                        isTarget = isTargetCoupon(ruleItem.getBusiId(), dtoItem.getCouType(), goodId, priceTotal, dtoItem.getValOver());
                        break;
                    case 81://款式
//                        isTarget = isTargetCoupon(ruleItem.getBusiId(), dtoItem.getCouType(), produceId, priceTotal, dtoItem.getValOver());
                        break;
                    case 100://全场
                        if (dtoItem.getCouType().equals(2)) {
                            if (priceTotal.compareTo(dtoItem.getValOver()) >= 0) {
                                isTarget = true;
                            } else {
                                isTarget = false;
                            }
                        } else {
                            isTarget = true;
                        }
                        break;
                    default:
                        isTarget = false;
                        break;
                }
            }

            if (dtoItem.getUseRules().size() == 0 && !dtoItem.getBusiType().equals(0)) {
                isTarget = false;
            }
        }
        //券类别
        if (dtoItem.getBusiType().equals(3)) {
            vo.setCouType(101);
        } else {
            vo.setCouType(dtoItem.getCouType());
        }
        int state = getCouponState(now, dtoItem.getDuedAt(), dtoItem.getBindAt(), dtoItem.getState());

        if (isTarget) {
            vo.setState(state);
        } else {
            vo.setState(state == 1 ? 21 : state);//不在目标范围 如果可用改为不可用21
        }
        vo.setUseRules(rulesVoList);
        return vo;
    }

    /**
     * @param busiId     适用id
     * @param targetId   目标id(例如 演出id，场次id，票种id)
     * @param priceTotal 待支付总金额
     * @param valOver    满减~满
     * @return
     */
    public static Boolean isTargetCoupon(String busiId,
                                         Integer couType,
                                         String targetId,
                                         BigDecimal priceTotal,
                                         BigDecimal valOver) {
        boolean isTarget = false;
        ArrayList<String> targetIdList = new ArrayList(Arrays.asList(targetId.split(",")));
        if (targetIdList.contains(busiId)) {//判断id 对应
            if (couType.equals(2)) {
                if (priceTotal.compareTo(valOver) >= 0) {
                    isTarget = true;
                }
            } else {
                isTarget = true;
            }
        }
        return isTarget;
    }

    /**
     * 获取券状态
     *
     * @param currentTime 当前服务器时间
     * @param expireAt    券过期时间
     * @param state       券状态
     * @return 判断过后的券状态
     */
    public static Integer getCouponState(LocalDateTime currentTime, LocalDateTime expireAt, LocalDateTime effectAt, Integer state) {
        //券状态
        Integer data;
        if (state.equals(1)) {
            if (currentTime.isAfter(expireAt)) {
                data = 3;
            } else if (currentTime.isBefore(effectAt)) {
                data = 31;
            } else {
                data = state;
            }
        } else {
            data = state;
        }
        return data;
    }

    /**
     * 根据券id获取Dto
     *
     * @param dtoList   CouponBaseDtoList
     * @param uCouponId 券唯一id
     * @return CandyUserCouponBasicDto
     */
    public static CandyUserCouponBasicDto getSingleDtoByUCouponId(List<CandyUserCouponBasicDto> dtoList, String uCouponId) {
        for (CandyUserCouponBasicDto dtoItem : dtoList) {
            if (dtoItem.getUcouponId().equals(uCouponId)) {
                return dtoItem;
            }
        }
        return null;
    }

    /**
     * 使用券
     *
     * @param dtoList   CouponBaseDtoList
     * @param uCouponId 券唯一id
     * @return List<CandyUserCouponBasicDto>
     */
    public static List<CandyUserCouponBasicDto> useCoupon(List<CandyUserCouponBasicDto> dtoList, String uCouponId, String content) {
        boolean isHas = false;
        for (CandyUserCouponBasicDto dtoItem : dtoList) {
            if (dtoItem.getUcouponId().equals(uCouponId)) {
                if (dtoItem.getState().equals(1)) {
                    dtoItem.setState(5);
                    dtoItem.setUsedAt(LocalDateTime.now());
                    dtoItem.setUsedFor(content);
                    isHas = true;//券存在
                } else {
                    return null;//券不可用
                }
                break;
            }
        }
        if (!isHas) {
            return null;//券不存在
        }
        return dtoList;
    }

    /**
     * 回退券
     *
     * @param dtoList       CouponBaseDtoList
     * @param uCouponIdList 券唯一id list
     * @return List<CandyUserCouponBasicDto>
     */
    public static List<CandyUserCouponBasicDto> backCoupon(List<CandyUserCouponBasicDto> dtoList, ArrayList<String> uCouponIdList) {
        boolean isHas = false;
        for (CandyUserCouponBasicDto dtoItem : dtoList) {
            if (uCouponIdList.contains(dtoItem.getUcouponId())) {
                if (dtoItem.getState().equals(5)) {
                    dtoItem.setState(1);
                    dtoItem.setUsedFor("");
                    dtoItem.setUsedAt(null);
                    isHas = true;//券存在
                } else {
                }
            }
        }
        if (!isHas) {
            return null;//券不存在
        }
        return dtoList;
    }

    /**
     * 判断券是否在可兑换时间范围
     *
     * @param dto
     * @return
     */
    public static boolean CandyCanReceive(CandyCouponInfoDto dto) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startTime = dto.getRedeemStart();
        LocalDateTime endTime = dto.getRedeemStop();
        if (now.isAfter(startTime) && now.isBefore(endTime)) {
            return true;
        } else {
            return false;
        }
    }
}
