package com.hai.service.impl;

import com.google.common.base.Stopwatch;
import com.hai.common.exception.ErrorCode;
import com.hai.common.exception.ErrorHelp;
import com.hai.common.exception.SysCode;
import com.hai.common.security.UserCenter;
import com.hai.common.utils.DateUtil;
import com.hai.common.utils.IDGenerator;
import com.hai.common.utils.RedisUtil;
import com.hai.dao.*;
import com.hai.entity.*;
import com.hai.model.UserInfoModel;
import com.hai.service.*;
import com.hai.service.HighDiscountPackageService;
import io.lettuce.core.RedisURI;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @serviceName HighDiscountPackageServiceImpl.java
 * @author Sum1Dream
 * @version 1.0.0
 * @Description // 优惠券包 接口
 * @createTime 12:21 下午 2021/11/25
 **/
@Service("highDiscountPackageService")
public class HighDiscountPackageServiceImpl implements HighDiscountPackageService {

    @Resource
    private HighDiscountPackageMapper highDiscountPackageMapper;

    @Resource
    private HighDiscountPackageRecordMapper highDiscountPackageRecordMapper;

    @Resource
    private HighDiscountPackageDetailsService highDiscountPackageDetailsService;

    @Resource
    private HighDiscountAgentRelService highDiscountAgentRelService;

    @Resource
    private HighDiscountAgentCodeService highDiscountAgentCodeService;

    @Resource
    private HighDiscountPackageActualMapper discountPackageActualMapper;

    @Resource
    private HighDiscountPackageDiscountActualMapper discountPackageDiscountActualMapper;

    @Resource
    private HighDiscountPackageDeliverService discountPackageDeliverService;

    @Resource
    private HighDiscountInventoryRecordMapper discountInventoryRecordMapper;

    @Resource
    private HighUserService highUserService;

    @Resource
    private HighDiscountPackageService highDiscountPackageService;

    @Resource
    private HighDiscountUserRelMapper highDiscountUserRelMapper;

    @Resource
    private HighDiscountService highDiscountService;

    @Resource
    private HighDiscountPackageActualService discountPackageActualService;

    @Resource
    private HighDiscountPackageDiscountActualService discountPackageDiscountActualService;

    @Resource
    private UserCenter userCenter;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public List<HighDiscountPackage> getDiscountPackageList(Map<String, Object> map) {

        HighDiscountPackageExample example = new HighDiscountPackageExample();
        HighDiscountPackageExample.Criteria criteria = example.createCriteria();

        if (MapUtils.getInteger(map, "companyId") != null) {
            criteria.andCompanyIdEqualTo(MapUtils.getInteger(map, "companyId"));
        }

        if (MapUtils.getInteger(map, "usingAttribution") != null) {
            criteria.andUsingAttributionEqualTo(MapUtils.getInteger(map, "usingAttribution"));
        }

        if (MapUtils.getString(map, "title") != null) {
            criteria.andTitleLike("%" + MapUtils.getString(map, "title") + "%");
        }

        if (MapUtils.getInteger(map, "salesType") != null) {
            criteria.andSalesTypeEqualTo(MapUtils.getInteger(map, "salesType"));
        }

        if (MapUtils.getInteger(map, "status") != null) {
            criteria.andStatusEqualTo(MapUtils.getInteger(map, "status"));
        } else {
            criteria.andStatusNotEqualTo(4);
        }

        example.setOrderByClause("created_time desc");

        return highDiscountPackageMapper.selectByExample(example);
    }

    @Override
    public HighDiscountPackage findDiscountPackageById(Integer id) {
        return highDiscountPackageMapper.selectByPrimaryKey(id);
    }

    @Override
    public HighDiscountPackage getCallExclusive(Integer usingAttribution, Integer companyId) {
        HighDiscountPackageExample example = new HighDiscountPackageExample();
        HighDiscountPackageExample.Criteria criteria = example.createCriteria();
        criteria.andUsingAttributionEqualTo(usingAttribution).andStatusNotEqualTo(4).andCompanyIdEqualTo(companyId);
        List<HighDiscountPackage> list = highDiscountPackageMapper.selectByExample(example);

        if (list.size() == 0) {
            return  null;
        } else {
            return list.get(0);
        }
    }

    @Override
    public void insertDiscountPackage(HighDiscountPackage highDiscountPackage) {
        highDiscountPackageMapper.insert(highDiscountPackage);
    }

    @Override
    public void updateDiscountPackage(HighDiscountPackage highDiscountPackage) {
        highDiscountPackageMapper.updateByPrimaryKey(highDiscountPackage);
    }

    @Override
    public List<HighDiscountPackageRecord> getDiscountPackageRecordList(Map<String, Object> map) {

        HighDiscountPackageRecordExample example = new HighDiscountPackageRecordExample();
        HighDiscountPackageRecordExample.Criteria criteria = example.createCriteria();

        if (MapUtils.getInteger(map, "companyId") != null) {
            criteria.andCompanyIdEqualTo(MapUtils.getInteger(map, "companyId"));
        }

        if (MapUtils.getInteger(map, "usingAttribution") != null) {
            criteria.andUsingAttributionEqualTo(MapUtils.getInteger(map, "usingAttribution"));
        }

        if (MapUtils.getString(map, "discountPackageTitle") != null) {
            criteria.andDiscountPackageTitleLike("%" + MapUtils.getString(map, "discountPackageTitle") + "%");
        }

        if (MapUtils.getString(map, "recordNo") != null) {
            criteria.andRecordNoLike("%" + MapUtils.getString(map, "recordNo") + "%");
        }

        if (MapUtils.getInteger(map, "salesType") != null) {
            criteria.andSalesTypeEqualTo(MapUtils.getInteger(map, "salesType"));
        }

        if (MapUtils.getString(map, "phone") != null) {
            criteria.andExt1Like("%" + MapUtils.getString(map, "phone") + "%");
        }

        return highDiscountPackageRecordMapper.selectByExample(example);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addDiscountPackageStock(HighDiscountPackage highDiscountPackage, UserInfoModel userInfoModel, Integer num) throws Exception {

        Map<String, Object> mapRule = new HashMap<>();
        mapRule.put("discountPackageId", highDiscountPackage.getId());

        // 查询优惠券包规则
        List<HighDiscountPackageDetails> discountPackageDetailsList = highDiscountPackageDetailsService.getDiscountPackageDetailsList(mapRule);

        // 生成优惠券包实际库存实体
        HighDiscountPackageActual discountPackageActual = new HighDiscountPackageActual();
        discountPackageActual.setDiscountPackageId(highDiscountPackage.getId());
        discountPackageActual.setCreatedUserId(userInfoModel.getSecUser().getId().intValue());
        // 状态： 1: 待分配 2:预分配（售卖）3:已分配
        discountPackageActual.setStatus(1);

        for (int i = 0; i < num; i++) {
            discountPackageActual.setCreatedTime(new Date());
            discountPackageActualMapper.insert(discountPackageActual);

            // 循环 优惠券包规则详情 列表
            for (HighDiscountPackageDetails detailsList : discountPackageDetailsList) {
                // 查询代理商与优惠券关系 列表
                HighDiscountAgentRel discountAgentRel = highDiscountAgentRelService.getRelByDiscountAgent(detailsList.getDiscountId().longValue(), detailsList.getAgentId());
                List<HighDiscountAgentCode> discountAgentCodeList = highDiscountAgentCodeService.getDiscountAgentCodByLimit(discountAgentRel.getId() , detailsList.getNum().longValue());

                if (discountAgentCodeList.size() < detailsList.getNum()) {
                    throw ErrorHelp.genException(SysCode.System , ErrorCode.COMMON_ERROR , detailsList.getDiscountName() +"优惠券库存不足");
                }

                // 优惠券
                for (HighDiscountAgentCode discountAgentCode : discountAgentCodeList) {
                    HighDiscountPackageDiscountActual discountPackageDiscountActual = new HighDiscountPackageDiscountActual();
                    discountPackageDiscountActual.setDiscountPackageId(highDiscountPackage.getId());
                    discountPackageDiscountActual.setDiscountPackageActualId(discountPackageActual.getId());
                    discountPackageDiscountActual.setCreatedUserId(userInfoModel.getSecUser().getId().intValue());
                    discountPackageDiscountActual.setCreatedTime(new Date());
                    discountPackageDiscountActual.setAgentDiscountCodeId(discountAgentCode.getId());
                    discountPackageDiscountActual.setStatus(1);
                    discountPackageDiscountActual.setDiscountId(detailsList.getDiscountId().longValue());
                    discountPackageDiscountActual.setAgentId(detailsList.getAgentId());
                    discountPackageDiscountActualMapper.insert(discountPackageDiscountActual);

                    // 修改优惠券二维码状态
                    discountAgentCode.setStatus(5);
                    highDiscountAgentCodeService.updateCode(discountAgentCode);

                }

            }
        }

        // 设置库存
        int surplusStock = highDiscountPackage.getSurplusStock() == null ? 0 :highDiscountPackage.getSurplusStock();
        int totalStock = highDiscountPackage.getTotalStock() == null ? 0 :highDiscountPackage.getTotalStock();

        // 新增补库记录
        HighDiscountInventoryRecord discountInventoryRecord = new HighDiscountInventoryRecord();
        discountInventoryRecord.setDiscountPackageId(highDiscountPackage.getId());
        discountInventoryRecord.setDiscountPackageTitle(highDiscountPackage.getTitle());
        discountInventoryRecord.setCreatedUserId(userInfoModel.getSecUser().getId().intValue());
        discountInventoryRecord.setCompanyId(userInfoModel.getBsCompany().getId().intValue());
        discountInventoryRecord.setCreatedTime(new Date());
        discountInventoryRecord.setStatus(1);
        discountInventoryRecord.setStockNum(num);
        discountInventoryRecord.setFrontStockNum(highDiscountPackage.getSurplusStock());
        discountInventoryRecord.setNowStockNum(surplusStock + num);

        discountInventoryRecordMapper.insert(discountInventoryRecord);

        // 设置库存
        highDiscountPackage.setTotalStock(totalStock + num);
        highDiscountPackageMapper.updateByPrimaryKey(highDiscountPackage);
    }


    @Override
    @Transactional(propagation= Propagation.REQUIRES_NEW)
    public HighDiscountPackageActual freeUserDiscountPackage(Map<String , Object> map) throws Exception {


        HighDiscountPackage highDiscountPackage = highDiscountPackageService.findDiscountPackageById(MapUtils.getInteger(map , "discountPackageId"));

        // 查询优惠券包实际库存
        HighDiscountPackageActual discountPackageActual = discountPackageActualService.getHighDiscountPackageActualList(highDiscountPackage.getId()).get(0);

        // 修改优惠券包实际库存为已使用
        discountPackageActual.setStatus(0);
        discountPackageActual.setUserId(MapUtils.getInteger(map , "userId"));
        discountPackageActual.setAllocationTime(new Date());
        discountPackageActualService.updateHighDiscountPackageActual(discountPackageActual);

        // 查询优惠券包实际库存中实际优惠券数量
        List<HighDiscountPackageDiscountActual> discountPackageDiscountActual = discountPackageDiscountActualService.getHighDiscountPackageDiscountActualList(discountPackageActual.getId());

        // 循环赠送优惠券
        for (HighDiscountPackageDiscountActual actualList: discountPackageDiscountActual) {

            HighDiscountUserRel highDiscountUserRel = new HighDiscountUserRel();
            highDiscountUserRel.setDiscountId(actualList.getDiscountId());
            highDiscountUserRel.setUserId(MapUtils.getLong(map , "userId"));
            highDiscountUserRel.setAgentId(actualList.getAgentId());
            highDiscountUserRel.setDiscountAgentCodeId(actualList.getAgentDiscountCodeId());
            highDiscountUserRel.setStatus(1);
            highDiscountUserRel.setCreateTime(new Date());

            HighDiscount highDiscount  = highDiscountService.getDiscountById(actualList.getDiscountId());

            // 计算使用有效期
            Calendar userEndTime = Calendar.getInstance();
            userEndTime.setTime(new Date());
            userEndTime.set(Calendar.HOUR_OF_DAY, 23);
            userEndTime.set(Calendar.MINUTE, 59);
            userEndTime.set(Calendar.SECOND, 59);
            userEndTime.add(Calendar.DATE, highDiscount.getEffectiveDay());
            highDiscountUserRel.setUseEndTime(userEndTime.getTime());

            HighDiscountAgentCode discountAgentCode = highDiscountAgentCodeService.getCodeById(actualList.getAgentDiscountCodeId());

            // 修改优惠券二维码状态
            discountAgentCode.setStatus(2);
            highDiscountAgentCodeService.updateCode(discountAgentCode);

            // 新增优惠券与用户的绑定关系
            highDiscountUserRelMapper.insert(highDiscountUserRel);

            // 修改优惠券包实际库存实际优惠券状态
            actualList.setStatus(0);
            discountPackageDiscountActualService.updateHighDiscountPackageDiscountActual(actualList);
        }

        // 增加赠送记录
        HighDiscountPackageRecord discountPackageRecord = new HighDiscountPackageRecord();
        discountPackageRecord.setDiscountPackageId(highDiscountPackage.getId());
        discountPackageRecord.setDiscountPackageTitle(highDiscountPackage.getTitle());
        discountPackageRecord.setCompanyId(highDiscountPackage.getCompanyId());
        discountPackageRecord.setStatus(1);
        discountPackageRecord.setUsingAttribution(1);
        discountPackageRecord.setRecordNo("DP" + DateUtil.date2String(new Date(),"yyyyMMddHHmmss") + IDGenerator.nextId(5) );
        discountPackageRecord.setSalesType(2);
        discountPackageRecord.setUserId(MapUtils.getInteger(map , "userId"));
        discountPackageRecord.setExt1(MapUtils.getString(map , "userPhone"));
        discountPackageRecord.setCreatedTime(new Date());
        highDiscountPackageRecordMapper.insert(discountPackageRecord);

        return discountPackageActual;
    }

    @Override
    @Transactional(propagation= Propagation.REQUIRES_NEW)
    public String giveAway(Long packageId, List<String> phoneList) throws Exception {
        UserInfoModel userInfoModel = userCenter.getSessionModel(UserInfoModel.class);

        // 查询优惠券包
        HighDiscountPackage discountPackage = findDiscountPackageById(packageId.intValue());
        if (discountPackage == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "没有找到券包信息");
        }
        if (!discountPackage.getStatus().equals(1)) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "券包状态错误");
        }
        // 查询卷包库存
        Long stockCount = discountPackageActualService.getDiscountPackageNum(packageId.intValue());
        if (phoneList.size() > stockCount.intValue()) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "卷包库存不足");
        }

        // 赠送记录流水
        String serialNum = System.currentTimeMillis()+"";

        HighDiscountPackageDeliver discountPackageDeliver = new HighDiscountPackageDeliver();
        discountPackageDeliver.setPackageId(packageId);
        discountPackageDeliver.setPackageName(discountPackage.getTitle());
        discountPackageDeliver.setSerialNumber(serialNum);
        discountPackageDeliver.setOpUserId(userInfoModel.getSecUser().getId());
        discountPackageDeliver.setOpUserName(userInfoModel.getSecUser().getUserName());
        discountPackageDeliverService.insertDeliver(discountPackageDeliver);

        // 查询出来系统中的用户
        Map<String, String> userMap = new HashMap<>();
        userMap.put("status", "1");
        List<HighUser> listUser = highUserService.getListUser(userMap);

        new Thread(() -> {
            int alreadyProcessedNum = 0;
            for (String phone : phoneList) {
                try {
                    // 根据手机号查询用户
                    List<HighUser> userList = listUser.stream().filter(p -> p.getPhone().equals(phone)).collect(Collectors.toList());
                    if (userList.size() > 0) {
                        Map<String, Object> freeMap = new HashMap<>();
                        freeMap.put("discountPackageId", packageId);
                        freeMap.put("userId", userList.get(0).getId());
                        freeMap.put("userPhone", userList.get(0).getPhone());
                        HighDiscountPackageActual packageActual = freeUserDiscountPackage(freeMap);

                        HighDiscountPackageDeliverUser deliverUser = new HighDiscountPackageDeliverUser();
                        deliverUser.setPackageDeliverId(discountPackageDeliver.getId());
                        deliverUser.setSerialNumber(System.currentTimeMillis()+"");
                        deliverUser.setPackageId(packageId);
                        deliverUser.setPackageName(discountPackage.getTitle());
                        deliverUser.setPackageActualId(packageActual.getId().longValue());
                        deliverUser.setUserId(userList.get(0).getId());
                        deliverUser.setUserPhone(userList.get(0).getPhone());
                        deliverUser.setStatus(2);
                        deliverUser.setOpUserId(userInfoModel.getSecUser().getId());
                        deliverUser.setOpUserName(userInfoModel.getSecUser().getUserName());
                        discountPackageDeliverService.insertDeliverUser(deliverUser);
                    } else {
                        // 注册用户信息
                        HighUser user = new HighUser();
                        user.setName("用户" + IDGenerator.nextId(5));
                        user.setPhone(phone);
                        user.setRegTime(new Date());
                        user.setGold(0);
                        user.setStatus(1);
                        user.setInfoCompleteStatus(1); // 用户信息完整状态 0：完整 1：需要填写用户信息 2：需要填写手机号
                        highUserService.insertUser(user , null , null);

                        // 赠送卷包
                        Map<String, Object> freeMap = new HashMap<>();
                        freeMap.put("discountPackageId", packageId);
                        freeMap.put("userId", user.getId());
                        freeMap.put("userPhone", user.getPhone());
                        HighDiscountPackageActual packageActual = freeUserDiscountPackage(freeMap);

                        HighDiscountPackageDeliverUser deliverUser = new HighDiscountPackageDeliverUser();
                        deliverUser.setPackageDeliverId(discountPackageDeliver.getId());
                        deliverUser.setSerialNumber(System.currentTimeMillis()+"");
                        deliverUser.setPackageId(packageId);
                        deliverUser.setPackageName(discountPackage.getTitle());
                        deliverUser.setPackageActualId(packageActual.getId().longValue());
                        deliverUser.setUserId(userList.get(0).getId());
                        deliverUser.setUserPhone(userList.get(0).getPhone());
                        deliverUser.setStatus(2);
                        discountPackageDeliverService.insertDeliverUser(deliverUser);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    alreadyProcessedNum++;
                    redisUtil.set(serialNum, alreadyProcessedNum);
                }
            }
            discountPackageDeliver.setStatus(2);
            discountPackageDeliverService.updateDeliver(discountPackageDeliver);
            redisUtil.del(serialNum);
        }).start();
        return serialNum;
    }
}
