package com.hfkj.service.impl;

import com.ccb.wlpt.util.StringUtil;
import com.hfkj.common.exception.BaseException;
import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.dao.BsStoreDiscountActivityPartakeUserMapper;
import com.hfkj.entity.*;
import com.hfkj.service.BsStoreDiscountActivityPartakeUserRecordService;
import com.hfkj.service.BsStoreDiscountActivityPartakeUserService;
import com.hfkj.service.BsStoreDiscountActivityService;
import com.hfkj.sysenum.StoreDiscountActivityPartakeWayEnum;
import com.hfkj.sysenum.StoreDiscountActivityStatusEnum;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @className: BsStoreDiscountActivityPartakeUserServiceImpl
 * @author: HuRui
 * @date: 2023/3/14
 **/
@Service("storeDiscountActivityPartakeUserService")
public class BsStoreDiscountActivityPartakeUserServiceImpl implements BsStoreDiscountActivityPartakeUserService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private BsStoreDiscountActivityService storeDiscountActivityService;
    @Resource
    private BsStoreDiscountActivityPartakeUserMapper storeDiscountActivityPartakeUserMapper;
    @Resource
    private BsStoreDiscountActivityPartakeUserRecordService storeDiscountActivityPartakeUserRecordService;
    @Override
    public void editData(BsStoreDiscountActivityPartakeUser storeDiscountActivityPartakeUser) {
        if (storeDiscountActivityPartakeUser.getId() == null) {
            storeDiscountActivityPartakeUser.setStatus(1);
            storeDiscountActivityPartakeUser.setCreateTime(new Date());
            storeDiscountActivityPartakeUser.setUpdateTime(new Date());
            storeDiscountActivityPartakeUserMapper.insert(storeDiscountActivityPartakeUser);
        } else {
            storeDiscountActivityPartakeUser.setUpdateTime(new Date());
            storeDiscountActivityPartakeUserMapper.updateByPrimaryKey(storeDiscountActivityPartakeUser);
        }
    }

    @Override
    public BsStoreDiscountActivityPartakeUser getPartakeUser(String phone, Long activityId) {
        BsStoreDiscountActivityPartakeUserExample example = new BsStoreDiscountActivityPartakeUserExample();
        example.createCriteria().andUserPhoneEqualTo(phone).andDiscountActivityIdEqualTo(activityId);
        List<BsStoreDiscountActivityPartakeUser> list = storeDiscountActivityPartakeUserMapper.selectByExample(example);
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public void receiveDiscount(String phone, List<Long> activityIds) {
        activityIds = activityIds.stream().distinct().collect(Collectors.toList());
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("RECEIVE_DISCOUNT" + phone, phone);
        try {
            if(lock) {
                //加锁成功...
                for (Long activityId : activityIds) {
                    // 查询活动
                    BsStoreDiscountActivity activity = storeDiscountActivityService.getDetailById(activityId);
                    if (activity == null) {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到活动");
                    }
                    if (!activity.getStatus().equals(StoreDiscountActivityStatusEnum.status2.getNumber())) {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, "活动已结束");
                    }
                    if (new Date().compareTo(activity.getEndTime()) >= 1) {
                        throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "活动已结束");
                    }
                    // 扫码领券
                    if (activity.getPartakeWay().equals(StoreDiscountActivityPartakeWayEnum.type3.getNumber())) {
                        // 每日
                        if (activity.getRestrictType().equals(1) && activity.getRestrictPartakeNum() != 0) {
                            Calendar startTime = Calendar.getInstance();
                            startTime.setTime(new Date());
                            startTime.set(Calendar.HOUR_OF_DAY, 00);
                            startTime.set(Calendar.MINUTE, 00);
                            startTime.set(Calendar.SECOND, 00);

                            Calendar endTime = Calendar.getInstance();
                            endTime.setTime(new Date());
                            endTime.set(Calendar.HOUR_OF_DAY, 23);
                            endTime.set(Calendar.MINUTE, 59);
                            endTime.set(Calendar.SECOND, 59);

                            Long partakeNum = storeDiscountActivityPartakeUserRecordService.getPartakeNum(phone, activityId, startTime.getTime(), endTime.getTime());
                            if (partakeNum.intValue() >= activity.getRestrictPartakeNum()) {
                                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "今日领取上限");
                            }
                        }
                    }

                    BsStoreDiscountActivityPartakeUser partakeUser = getPartakeUser(phone, activityId);
                    if (partakeUser == null) {
                        partakeUser = new BsStoreDiscountActivityPartakeUser();
                        partakeUser.setPartakeTotalNum(0);
                        partakeUser.setPartakeSurplusNum(0);
                        partakeUser.setPartakeUseNum(0);
                    }
                    partakeUser.setDiscountActivityId(activity.getId());
                    partakeUser.setDiscountActivityName(activity.getName());
                    partakeUser.setDiscountType(activity.getDiscountType());
                    partakeUser.setDiscountCondition(activity.getDiscountCondition());
                    partakeUser.setDiscountPrice(activity.getDiscountPrice());
                    partakeUser.setStartTime(activity.getStartTime());
                    partakeUser.setEndTime(activity.getEndTime());
                    partakeUser.setUserPhone(phone);
                    partakeUser.setPartakeTotalNum(partakeUser.getPartakeTotalNum() + 1);
                    partakeUser.setPartakeSurplusNum(partakeUser.getPartakeSurplusNum() + 1);
                    editData(partakeUser);

                    BsStoreDiscountActivityPartakeUserRecord record = new BsStoreDiscountActivityPartakeUserRecord();
                    record.setUserPhone(phone);
                    record.setDiscountActivityId(activity.getId());
                    record.setDiscountActivityName(activity.getName());
                    record.setDiscountType(activity.getDiscountType());
                    record.setDiscountCondition(activity.getDiscountCondition());
                    record.setDiscountPrice(activity.getDiscountPrice());
                    storeDiscountActivityPartakeUserRecordService.insertRecord(record);
                }
            } else {
                System.out.println("加锁失败");
                Thread.sleep(100);   // 加锁失败，重试
                receiveDiscount(phone, activityIds);
            }
        } catch (BaseException e) {
            throw e;

        } catch (Exception e) {
            System.out.println(e);
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "领取失败，请稍后重试");

        } finally {
            // 删除key，释放锁
            redisTemplate.delete("RECEIVE_DISCOUNT" + phone);
        }
    }

    @Override
    public List<BsStoreDiscountActivityPartakeUser> getList(Map<String, Object> param) {
        BsStoreDiscountActivityPartakeUserExample example = new BsStoreDiscountActivityPartakeUserExample();
        BsStoreDiscountActivityPartakeUserExample.Criteria criteria = example.createCriteria();

        if (StringUtils.isNotBlank(MapUtils.getString(param, "userPhone"))) {
            criteria.andUserPhoneEqualTo(MapUtils.getString(param, "userPhone"));
        }

        if (MapUtils.getInteger(param, "status") != null) {
            criteria.andStatusEqualTo(MapUtils.getInteger(param, "status"));
        }

        example.setOrderByClause("create_time desc");
        return storeDiscountActivityPartakeUserMapper.selectByExample(example);
    }

    @Override
    public List<BsStoreDiscountActivityPartakeUser> getUseListByPhone(String phone) {
        BsStoreDiscountActivityPartakeUserExample example = new BsStoreDiscountActivityPartakeUserExample();
        example.createCriteria().andUserPhoneEqualTo(phone).andStatusEqualTo(1).andPartakeSurplusNumGreaterThanOrEqualTo(1);
        example.setOrderByClause("create_time desc");
        return storeDiscountActivityPartakeUserMapper.selectByExample(example);
    }

}
