package com.izouma.nineth.service;

import com.izouma.nineth.config.SysConstants;
import com.izouma.nineth.converter.InvitePrizeConverter;
import com.izouma.nineth.domain.*;
import com.izouma.nineth.domain.Collection;
import com.izouma.nineth.enums.*;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.*;
import com.izouma.nineth.service.pay.UniformPayUtil;
import com.izouma.nineth.service.rewardpoints.UserIntegralChangeLogService;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.persistence.Column;
import javax.persistence.Convert;
import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class ActivityInviteService {
    private InviteDateRepo inviteDateRepo;
    private AirDropService airDropService;
    private CollectionRepo collectionRepo;
    private ActivitySurpriseBoxRepo activitySurpriseBoxRepo;
    private UserRepo userRepo;
    private ActivityInviteRepo activityInviteRepo;
    private UserBankCardRepo userBankCardRepo;
    private SysConfigService sysConfigService;
    private UniformPayUtil uniformPayUtil;
    private AssetRepo assetRepo;
    private UserService userService;

    private UserIntegralChangeLogService userIntegralChangeLogService;


    /**
     * 活动结束后发放奖励
     *
     * @param activityInvite
     */
    @Transactional
    public void activityTerminationReward(ActivityInvite activityInvite) {
        //根据活动ID查询成功邀请数据
//        List<InviteDate> inviteDateList = inviteDateRepo.findActivityIdDate(activityInvite.getId(), InvitationNote.SUCCESSFULLY.ordinal());
//        if (activityInvite.getPhones() == null) {
//            activityInvite.setPhones(new ArrayList<>());
//        }
//        //过滤掉已经发放过奖励的人
//        inviteDateList.removeIf(e -> activityInvite.getPhones().contains(e.getInviterUserId()));
//        Map<Long, List<InviteDate>> map = inviteDateList.stream().collect(Collectors.groupingBy(InviteDate::getInviterUserId));
//
//        //需要发奖励的人
//        Map<InvitePrize, List<Long>> invitePrizeMap = new HashMap<>();
//        if (AwardDistributionType.ONE == activityInvite.getAwardDistributionType()) {
//            //  ONE("活动结束后发放所有已达成条件的奖励")
//            for (InvitePrize invitePrize : activityInvite.getInvitePrizeList()) {
//                List<Long> list = new ArrayList<>();
//                map.forEach((k, v) -> {
//                    if (v.size() >= invitePrize.getInviteNum()) {
//                        list.add(k);
//                    }
//                });
//                if (list.size() > 0) {
//                    invitePrizeMap.put(invitePrize, list);
//                }
//            }
//        } else if (AwardDistributionType.TWO == activityInvite.getAwardDistributionType()) {
//            //  TWO("活动结束后按最高奖励发放");
//            map.forEach((k, v) -> {
//                InvitePrize userinvitePrize = null;
//                for (InvitePrize invitePrize : activityInvite.getInvitePrizeList()) {
//                    if (v.size() >= invitePrize.getInviteNum()) {
//                        if (userinvitePrize == null) {
//                            userinvitePrize = invitePrize;
//                        }
//                        if (userinvitePrize.getInviteNum() < invitePrize.getInviteNum()) {
//                            userinvitePrize = invitePrize;
//                        }
//                    }
//                }
//                if (userinvitePrize != null) {
//                    invitePrizeMap.computeIfAbsent(userinvitePrize, k1 -> new ArrayList<>());
//                    invitePrizeMap.get(userinvitePrize).add(k);
//                }
//            });
//        }
//        try {
//            //发放奖励
//            Map<Long, Integer> airDropAwardMap = new HashMap<>();
//            invitePrizeMap.forEach((invitePrize, userIds) -> {
//                List<User> users = userRepo.findByIdInAndDelFalse(userIds);
//                List<String> phoneList = users.stream().map(User::getPhone).collect(Collectors.toList());
//                long timeMillis = System.currentTimeMillis();
//                Long duration = System.currentTimeMillis() - timeMillis;
//                boolean ok = award(invitePrize, phoneList, userIds, "邀请新人获得" + invitePrize.getType().getDescription() + "奖励");
//                log.info("邀请活动结束批投放惊喜盒子，数量：{} ,耗时 {}", userIds.size(), duration);
//                //保存已经发放的名单
//                if (ok) {
//                    activityInvite.getPhones().addAll(userIds);
//                    activityInviteRepo.save(activityInvite);
//                    //记录空投次数
//                    userIds.forEach(userId -> airDropAwardMap.put(userId, airDropAwardMap.getOrDefault(userId, 1)));
//                } else {
//                    log.info("投放失败名单{}，奖品{} ,耗时 {}", userIds, invitePrize, duration);
//                }
//            });
//            List<InviteDate> InviteDatelist = new ArrayList<>();
//            airDropAwardMap.forEach((userId, airDropAwardCount) -> {
//                List<InviteDate> list = map.get(userId);
//                if (list.size() > 0) {
//                    InviteDate inviteDate = list.get(0);
//                    inviteDate.setAirDropAward(inviteDate.getAirDropAward() + airDropAwardCount);
//                    InviteDatelist.add(inviteDate);
//                }
//            });
//            inviteDateRepo.saveAll(InviteDatelist);
//        } catch (Exception e) {
//            log.info("邀请活动结束批投放奖品报错", e);
//            throw new BusinessException("邀请活动结束批投放奖品报错");
//        }
    }

    /**
     * @param userId
     * @param bankNo
     * @param inviteeQualifications 1需要绑定银行卡  0需要绑定钱包 2,需要实名
     */
    @Transactional
    public void risingStar(Long userId, String bankNo, InviteeQualificationsType inviteeQualifications) {
        //是否绑定过银行卡,防止重复
        User user = userRepo.findById(userId).orElseThrow(new BusinessException("用户不存在"));
        if (!user.isBankCard()) {
            ActivityInvite activityInvite = activityInviteRepo.asdasdasfaf(LocalDateTime.now());
            if (Integer.valueOf(sysConfigService.getInt(SysConstants.TESTER_USER_ID)).longValue() == userId && activityInvite == null) {
                activityInvite = activityInviteRepo.findRecent();
            }
            //有活动 并且活动被邀请者完成条件不是当前类型 直接返回
            if (activityInvite != null && activityInvite.getInviteeQualifications() != inviteeQualifications.value) {
                return;
            }
            //一次有效
            user.setBankCard(true);
            userRepo.save(user);

            if (activityInvite == null || user.getInvitor() == null) {
                return;
            }
            //有邀请人 并且是在用户注册时间是在邀请时间内的 或者测试账号
            if (user.getCreatedAt().isAfter(activityInvite.getInviteStartdatetime()) || Integer.valueOf(sysConfigService.getInt(SysConstants.TESTER_USER_ID)).longValue() == userId) {
                User invitor = userRepo.findByIdAndDelFalse(user.getInvitor()).orElseThrow(new BusinessException("未找到邀请人"));
                InvitationNote remark = condition(activityInvite, invitor, bankNo, userId);
                List<InvitePrize> invitePrizeList = null;
                InvitePrize byInvitePrize = null;
                boolean automaticRewards = false;
                Long inviteIntegral = null;
                if (remark == InvitationNote.SUCCESSFULLY) {
                    //ZERO("每达到一个条件实时发放一次奖励"),ONE("活动结束后发放所有已达成条件的奖励"), TWO("活动结束后按最高奖励发放");
                    if (AwardDistributionType.ZERO == activityInvite.getAwardDistributionType()) {
                        //邀请数量
                        int inviteNum = 1 + inviteDateRepo.findinviterUserIdCount(activityInvite.getId(), invitor.getId(), InvitationNote.SUCCESSFULLY.ordinal());

                        if (activityInvite.getInvitePrizeList() != null && activityInvite.getInvitePrizeList().size() > 0) {
                            invitePrizeList = activityInvite.getInvitePrizeList().stream().filter(invitePrize -> inviteNum == invitePrize.getInviteNum()).collect(Collectors.toList());
                            automaticRewards = invitePrizeList.size() > 0;
                        }
                        //被邀请者获得奖品
                        if (activityInvite.getByInvitePrize() != null && activityInvite.getByInvitePrize().getType() != null) {
                            byInvitePrize = activityInvite.getByInvitePrize();
                            automaticRewards = true;
                        }

                    }

                    //发放奖励
                    if(activityInvite.getInviteIntegral() != null && activityInvite.getInviteIntegral() > 0){
                        inviteIntegral = activityInvite.getInviteIntegral();
                        automaticRewards = true;
                    }

                }

                inviteDateRepo.save(InviteDate.builder()
                        .activityId(activityInvite.getId())
                        .inviteeUserId(user.getId())
                        .inviterUserId(invitor.getId())
                        .name(activityInvite.getName())
                        .inviterPhone(invitor.getPhone())
                        .airDropAward(0)
                        .automaticRewards(automaticRewards)
                        .byInvitePrize(byInvitePrize)
                        .invitePrizeList(invitePrizeList)
                        .status(remark.ordinal())
                        .remark(remark.getDescription())
                        .inviteIntegral(inviteIntegral)
                        .build());
            }
        }
    }

    private InvitationNote condition(ActivityInvite activityInvite, User invitor, String bankNo, Long userId) {
        if (activityInvite.getInviteeQualifications() == InviteeQualificationsType.BIND_BANK_CARD.value && userBankCardRepo.findByBankNo(bankNo, userId) > 0) {
            return InvitationNote.DUPLICATE_BANK;
        }

        if (activityInvite.getHoldCollectionIds() != null && !activityInvite.getHoldCollectionIds().isEmpty()) {
            boolean hold = activityInvite.getHoldCollectionIds().stream().anyMatch(collectionId -> assetRepo.findAllByCollectionIdAndUserIdAndStatus(collectionId, invitor.getId(), AssetStatus.NORMAL).size() > 0);
            if (!hold) {
                return InvitationNote.SPECIFIED_COLLECTION;
            }
        }
        if (activityInvite.getInviterQualifications() != null && activityInvite.getInviterQualifications() == 1) {
            if (AuthStatus.SUCCESS != invitor.getAuthStatus()) {
                return InvitationNote.CERTAIN;
            }
        }
        if (activityInvite.getInviterQualifications() != null && activityInvite.getInviterQualifications() == 2) {
            if (AuthStatus.SUCCESS != invitor.getAuthStatus() || !uniformPayUtil.isBindBankCard(invitor.getId())) {
                return InvitationNote.UNBOUND_BANK;
            }
        }
        if (activityInvite.getInviterQualifications() != null && activityInvite.getInviterQualifications() == 3) {
            if (AuthStatus.SUCCESS != invitor.getAuthStatus() || !userService.whetherCreatewallet(invitor.getId())) {
                return InvitationNote.UNBOUND_WALLET;
            }
        }
        return InvitationNote.SUCCESSFULLY;
    }


    @Transactional
    public void sendPrize(List<InviteDate> listdata) {
        for (InviteDate inviteDate : listdata) {
            //邀请者获得的奖励
            List<InvitePrize> invitePrizeList = inviteDate.getInvitePrizeList();
            if (invitePrizeList != null && invitePrizeList.size() > 0) {
                userRepo.findById(inviteDate.getInviterUserId()).ifPresent(user -> invitePrizeList.forEach(invitePrize -> {
                    boolean result = award(invitePrize, List.of(Objects.requireNonNullElse(user.getPhone(), "1")), List.of(user.getId()), "邀请新人获得" + invitePrize.getType().getDescription() + "奖励");
                    if (result) {
                        inviteDate.setAirDropAward(inviteDate.getAirDropAward() + 1);//记录空投数量
                    }
                }));
            }
            //被邀请者获得奖励
            InvitePrize byInvitePrize = inviteDate.getByInvitePrize();
            if (byInvitePrize != null) {
                userRepo.findById(inviteDate.getInviteeUserId()).ifPresent(user -> award(byInvitePrize, List.of(Objects.requireNonNullElse(user.getPhone(), "1")), List.of(user.getId()), "新人获得" + byInvitePrize.getType().getDescription() + "奖励"));
            }

            if(inviteDate.getInviteIntegral() != null && inviteDate.getInviteIntegral() > 0){
                //发积分
                UserIntegralChangeLog changeLog = userIntegralChangeLogService.createByChangeType(IntegralChangeType.INVITE, inviteDate.getInviterUserId(),inviteDate.getInviteIntegral());
                changeLog.setSourceId(inviteDate.getId());
            }

            //完成发放奖励修改状态
            inviteDate.setAutomaticRewards(false);
        }
        inviteDateRepo.saveAll(listdata);
        log.info("发放奖励成功,数量：{}", listdata.size());
    }


    /**
     * 发放邀请奖励
     *
     * @param invitePrize
     * @param name
     */
    private boolean award(InvitePrize invitePrize, List<String> phoneList, List<Long> userIds, String name) {
        try {
            if (invitePrize.getType() == AirDropType.SURPRISE_BOX) {
                Optional<ActivitySurpriseBox> surpriseBox = activitySurpriseBoxRepo.findById(invitePrize.getInviteCollection());
                if (surpriseBox.isPresent() && surpriseBox.get().getBoxSum() > 0) {
                    AirDrop airDrop = AirDrop.builder()
                            .name(name)
                            .type(AirDropType.SURPRISE_BOX)
                            .surpriseBoxId(invitePrize.getInviteCollection())
                            .phone(phoneList)
                            .userIds(userIds)
                            .projectId(surpriseBox.get().getProjectId())
                            .build();
                    airDropService.surpriseBoxAirDrop(airDrop);
                    return true;
                }
            } else if (invitePrize.getType() == AirDropType.asset) {
                Optional<Collection> collection = collectionRepo.findById(invitePrize.getInviteCollection());
                if (collection.isPresent() && collection.get().getStock() > 0) {
                    airDropService.create(AirDrop.builder()
                            .name(name)
                            .type(AirDropType.asset)
                            .collectionId(invitePrize.getInviteCollection())
                            .phone(phoneList)
                            .userIds(userIds)
                            .projectId(collection.get().getProjectId())
                            .build());
                    return true;
                }
            }
        } catch (Exception e) {
            if (!(e instanceof BusinessException)) {
                log.info("发奖报错", e);
                throw e;
            }
        }
        return false;
    }
}
