package com.cyksj.service.mange.group;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cyksj.common.EnvCommonService;
import com.cyksj.common.constant.Constant;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
import com.cyksj.dto.RedisKey;
import com.cyksj.mapper.*;
import com.cyksj.mapper.manage.GroupsTripsAccountReplaceRecordMapper;
import com.cyksj.mapper.manage.cms.CmsUserMapper;
import com.cyksj.model.entity.*;
import com.cyksj.model.manage.views.AccountView;
import com.cyksj.model.manage.views.GroupsRelationView;
import com.cyksj.model.request.ReplaceTripsAccountReq;
import com.cyksj.model.views.GroupsAccountView;
import com.cyksj.redis.RedisService;
import com.cyksj.service.chatgpt.GptUserRechargeRecordService;
import com.cyksj.service.mange.AccountCommonService;
import com.cyksj.service.mange.CmsGroupService;
import com.cyksj.service.relation.GroupRelationClearService;
import com.cyksj.service.relation.GroupsRelationNetflixService;
import com.cyksj.service.sms.SmsService;
import com.cyksj.service.user.UserBindRelationService;
import com.cyksj.service.user.UserSysMsgNotifyService;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.param.Operator;
import com.ejlchina.searcher.util.MapBuilder;
import com.ejlchina.searcher.util.MapUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author chan
 * @date 2022/9/27 6:27 PM
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> implements CmsGroupService {

    private final GoodsDonSkuMapper skuMapper;

    private final GroupsRelationMapper relationMapper;

    private final OrderDonMapper orderDonMapper;

    private final AccountMapper accountMapper;

    private final BeanSearcher beanSearcher;

    private final GroupsTripsAccountReplaceRecordMapper replaceRecordMapper;

    private final CmsUserMapper cmsUserMapper;

    private final GoodsDonMapper goodsDonMapper;

    private final SmsService smsService;

    private final EnvCommonService envCommonService;

    private final RedisService redisService;

    private final GroupsMapper groupsMapper;

    private final AccountCommonService accountCommonService;

    private final GroupsRelationAlertMapper alertMapper;

    private final UserSysMsgNotifyService userSysMsgNotifyService;

    private final GroupsRelationNetflixService groupsRelationNetflixService;

    private final UserMapper userMapper;

    private final NetflixUserAccountSubmitRecoverRecordMapper netflixUserAccountSubmitRecoverRecordMapper;

    private final GroupRelationClearService clearService;

    private final UserBindRelationService userBindRelationService;

    private final NetflixUserAccountStatusRecordMapper netflixUserAccountStatusRecordMapper;

    private final GptUserRechargeRecordService gptUserRechargeRecordService;

    private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();


    @Override
    public GroupsTrips issuance(GroupsTrips groups, String verifyCodes, Boolean isRecover) {
        GoodsDonSku sku = skuMapper.selectById(groups.getSkuId());
        if (sku == null) {
            throw new BusinessRuntimeException("该商品规格不存在！");
        }
        List<String> verifyCodeList = null;
        if (StrUtil.isNotBlank(verifyCodes)) {
            verifyCodes = verifyCodes.replaceAll("\n", "");
            String[] verifyCodeArray = verifyCodes.split("\\*");
            verifyCodeList = Arrays.stream(verifyCodeArray).filter(str -> StrUtil.isNotBlank(str)).map(str -> str.trim()).collect(Collectors.toList());
        }
        groups.setNum(sku.getNum());
        groups.setAvailableNum(sku.getNum());
        if (groups.getAccountId() == null || accountMapper.selectById(groups.getAccountId()) == null) {
            throw new BusinessRuntimeException("该账号不存在");
        }
        groups.setStatus(GroupsTrips.Status.validity);
        this.save(groups);

        for (Integer i = 1; i <= groups.getNum(); i++) {
            GroupsRelation relation = new GroupsRelation();
            relation.setGroupsId(groups.getId());
            relation.setStatus(GroupsRelation.Status.none);
            relation.setNum(i);
            if (verifyCodeList != null && verifyCodeList.size() > 0 && verifyCodeList.size() >= i) {
                relation.setVerifyCode(verifyCodeList.get(i - 1));
            }
            NetflixUserAccountSubmitRecoverRecord recoverRecord = null;
            if (sku.getGoodsId() == Constant.NETFLIX_GID) {
                recoverRecord = updateRelationIfRecoverTicket(isRecover, sku, relation);
            }
            relationMapper.insert(relation);
            if (recoverRecord != null) {
                recoverRecord.setReplaceRelationId(relation.getId());
                netflixUserAccountSubmitRecoverRecordMapper.updateById(recoverRecord);
            }
        }
        Integer alertCount = alertMapper.selectCount(Wrappers.lambdaQuery(GroupsRelationAlert.class)
                .eq(GroupsRelationAlert::getSkuId, sku.getId())
                .last("limit 1"));
        if (alertCount > 0) {
            alertMapper.update(null, Wrappers.lambdaUpdate(GroupsRelationAlert.class)
                    .set(GroupsRelationAlert::getIsReset, true)
                    .eq(GroupsRelationAlert::getSkuId, sku.getId())
                    .eq(GroupsRelationAlert::getIsReset, false));
        }
        return groups;
    }

    @Override
    public void close(Long groupId) {
        GroupsTrips groupsTrips = this.getById(groupId);
        if(groupsTrips == null){
            throw new BusinessRuntimeException("非法参数.车队不存在");
        }
        Integer count = relationMapper.selectCount(Wrappers.lambdaQuery(GroupsRelation.class)
                .eq(GroupsRelation::getGroupsId, groupId)
                .ne(GroupsRelation::getUserId, 0)
                .ne(GroupsRelation::getStatus, GroupsRelation.Status.none));
        if (count > 0) {
            throw BusinessRuntimeException.getInstance("请移除该车队下的用户再进行删掉操作");
        }
        //可强制删除
        //后台记录
//        if (count > 0) {
//            List<GroupsRelation> groupsRelations = relationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class)
//                    .eq(GroupsRelation::getGroupsId, groupId)
//                    .ne(GroupsRelation::getStatus, GroupsRelation.Status.none));
//            if (groupsRelations.size() > 0) {
//                Account account = accountMapper.selectById(groupsTrips.getAccountId());
//                TASK_EXECUTOR.execute(() -> {
//                    if (redisService.setNx(String.format("%s-%s", groupId, groupsTrips.getAccount()), groupId, 10l)) {
//                        groupsRelations.forEach(data -> {
//                            DelGroupsTripsRecord delGroupsTripsRecord = new DelGroupsTripsRecord();
//                            delGroupsTripsRecord.setGroupsId(groupId);
//                            delGroupsTripsRecord.setGroupsStatus(groupsTrips.getStatus().name());
//                            if (account != null) {
//                                delGroupsTripsRecord.setAccount(account.getAccount());
//                                delGroupsTripsRecord.setPassword(account.getPassword());
//                            }
//                            delGroupsTripsRecord.setRelationId(data.getId());
//                            delGroupsTripsRecord.setSkuId(groupsTrips.getSkuId());
//                            delGroupsTripsRecord.setUserId(data.getUserId());
//                            delGroupsTripsRecord.setStartTime(data.getStartTime());
//                            delGroupsTripsRecord.setExpiryTime(data.getExpiryTime());
//                            delGroupsTripsRecord.setRelationStatus(data.getStatus().name());
//                            delGroupsTripsRecord.setType("delete");
//                            delGroupsTripsRecordMapper.insert(delGroupsTripsRecord);
//                        });
//                    }
//                });
//            }
//        }
        relationMapper.delete(Wrappers.lambdaQuery(GroupsRelation.class).eq(GroupsRelation::getGroupsId,groupId));
        this.removeById(groupId);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void setAccount(GroupsTrips groupsTrips) throws Exception {
        int count = count(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getAccountId, groupsTrips.getAccountId()));
        if (count > 0) {
            throw new BusinessRuntimeException("该账号已发车.请选择未发车账户");
        }
        Account account = accountMapper.selectById(groupsTrips.getAccountId());
        //将预备账号 类型替换掉
        if (account.getType() == 2) {
            int update = accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
                    .set(Account::getType, 1)
                    .eq(Account::getId, account.getId())
                    .eq(Account::getType, 2));
            if (update == 0) {
                throw BusinessRuntimeException.getInstance("该账号已配置车队");
            }
        }
        List<GroupsRelation> groupsRelations = relationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class).eq(GroupsRelation::getGroupsId, groupsTrips.getId()).eq(GroupsRelation::getStatus, GroupsRelation.Status.validity));
        GroupsTrips trips = beanSearcher.searchFirst(GroupsTrips.class, MapUtils.builder().field(GroupsTrips::getId, groupsTrips.getId()).onlySelect(GroupsTrips::getTitle).build());
        String title = "车票";
        if (trips != null && StrUtil.isNotBlank(trips.getTitle())) {
            title = trips.getTitle();
        }
        //配置midJourney安全码
        String verifyCodes = groupsTrips.getVerifyCodes();
        List<String> verifyCodeList = null;
        if (StrUtil.isNotBlank(verifyCodes)) {
            verifyCodes = verifyCodes.replaceAll("\n", "");
            String[] verifyCodesArray = verifyCodes.split("\\*");
            verifyCodeList = Arrays.stream(verifyCodesArray).filter(str -> StrUtil.isNotBlank(str)).map(str -> str.trim()).collect(Collectors.toList());
        }
        Boolean isPrdEnv = envCommonService.isPrdEnv();
        for (int i = 0; i < groupsRelations.size(); i++) {
            GroupsRelation relation = groupsRelations.get(i);
            if (relation.getExpiryTime() == null) {
                List<OrderDon> orderDonList = orderDonMapper.selectList(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, relation.getUserId()).eq(OrderDon::getRelationId, relation.getId()).eq(OrderDon::getStatus, OrderDon.Status.hasPayment));
                //加购车票
                if (orderDonList.isEmpty()) {
                    GoodsDonSku donSku = skuMapper.selectById(groupsTrips.getSkuId());
                    Date expiryTime = Optional.ofNullable(relation.getExpiryTime()).orElse(new Date());
                    Date newDate;
                    if (donSku.getDays() != null && donSku.getDays() > 0) {
                        newDate = DateUtil.offsetDay(expiryTime, donSku.getDays() * 1);
                    } else {
                        //奈飞月付 按30天计算
                        if (donSku.getId() == 4) {
                            newDate = DateUtil.offsetDay(expiryTime, 30);
                        } else {
                            newDate = DateUtil.offset(expiryTime, DateField.MONTH, donSku.getMonths() * 1);
                        }
                    }
                    relation.setExpiryTime(newDate);
                    relation.setStartTime(relation.getStartTime() == null ? new Date() : null);
                    relationMapper.updateById(relation);
                    return;
                }
                orderDonList.forEach((orderDon) -> {
                    //如果续费增加时间，如果首次则设置当前时间为初始时间
                    Date expiryTime = Optional.ofNullable(relation.getExpiryTime()).orElse(new Date());
                    log.info("设置账号，该用户 {} 初始时间:{} ", orderDon.getUserId(), DateUtil.format(expiryTime, "yyyy-MM-dd HH:mm:ss"));
                    GoodsDonSku donSku = skuMapper.selectById(orderDon.getSkuId());
                    Date newDate;
                    if (donSku.getDays() != null && donSku.getDays() > 0) {
                        newDate = DateUtil.offsetDay(expiryTime, donSku.getDays() * orderDon.getNum());
                    } else {
                        newDate = DateUtil.offset(expiryTime, DateField.MONTH, donSku.getMonths() * orderDon.getNum());
                    }
                    relation.setExpiryTime(newDate);
                    log.info("设置账号，该用户 {} 过期时间:{} ", orderDon.getUserId(), DateUtil.format(newDate, "yyyy-MM-dd HH:mm:ss"));
                    relation.setStartTime(relation.getStartTime() == null ? new Date() : null);
                    relationMapper.updateById(relation);
                    orderDon.setStatus(OrderDon.Status.complete);
                    orderDonMapper.updateById(orderDon);
                });
            }
            if (relation.getUserId() != 0 && isPrdEnv && relation.getYhsId() == 0) {
                //发送短信
                smsService.sendSmsToRelationUser(relation.getUserId(), Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title, account.getAccount());
            }
            if (verifyCodeList != null && verifyCodeList.size() > 0 && i < verifyCodeList.size()) {
                relation.setVerifyCode(verifyCodeList.get(i));
                relationMapper.updateById(relation);
            }
            //设置奈飞用户座位
            if (account.getGoodsId() == 1) {
                User user = userMapper.selectById(relation.getUserId());
                AtomicInteger start = new AtomicInteger(1);
                groupsRelationNetflixService.timingSetNetflix(relation.getNum(), user.getNickname(), account.getAccount(), account.getPassword(), relation.getExpiryTime(), start);
            }
        }
        if (groupsRelations.isEmpty() && verifyCodeList != null && verifyCodeList.size() > 0) {
            groupsRelations = relationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class).eq(GroupsRelation::getGroupsId, groupsTrips.getId()));
            for (int i = 0; i < groupsRelations.size(); i++) {
                GroupsRelation relation = groupsRelations.get(i);
                if (i < verifyCodeList.size()) {
                    relation.setVerifyCode(verifyCodeList.get(i));
                    relationMapper.updateById(relation);
                }
            }
        }
       groupsTrips.setStatus(GroupsTrips.Status.validity);
        GoodsDonSku sku = skuMapper.selectById(groupsTrips.getSkuId());
        //下架上过车的POE,PS AI账号 || GPT Plus独立规格 下架
//        if (Constant.DOWN_GOODS_PAY.contains(sku.getGoodsId()) || skuMapper.selectSingleSkuIdsByGoodsId(Constant.AI_goodsIds.get(0)).contains(groupsTrips.getSkuId())) {
//            Number number = beanSearcher.searchCount(GroupsRelation.class, MapUtils.builder()
//                    .field(GroupsRelation::getGroupsId, groupsTrips.getId())
//                    .field(GroupsRelation::getUserId, 0).op(Operator.NotEqual)
//                    .field(GroupsRelation::getStatus, GroupsRelation.Status.validity.name())
//                    .build());
//            if (number.intValue() > 0) {
//                groupsTrips.setStatus(GroupsTrips.Status.down);
//            }
//        }
	    //独立车位 车队下架
	    if (sku.getNum() != null && sku.getNum() == 1) {
		    Number number = beanSearcher.searchCount(GroupsRelation.class, MapUtils.builder()
				    .field(GroupsRelation::getGroupsId, groupsTrips.getId())
				    .field(GroupsRelation::getUserId, 0).op(Operator.NotEqual)
				    .field(GroupsRelation::getStatus, GroupsRelation.Status.validity.name())
				    .build());
		    if (number.intValue() > 0) {
			    groupsTrips.setStatus(GroupsTrips.Status.down);
		    }
	    }
       updateById(groupsTrips);

        GoodsDon goodsDon = goodsDonMapper.selectById(account.getGoodsId());
        userSysMsgNotifyService.recordUserAccountSetSysMsg(account.getGoodsId(), groupsTrips.getSkuId(), groupsRelations, account.getAccount(), goodsDon.getTitle());

        Integer alertCount = alertMapper.selectCount(Wrappers.lambdaQuery(GroupsRelationAlert.class)
                .eq(GroupsRelationAlert::getSkuId, sku.getId())
                .last("limit 1"));
        if (alertCount > 0) {
            alertMapper.update(null, Wrappers.lambdaUpdate(GroupsRelationAlert.class)
                    .set(GroupsRelationAlert::getIsReset, true)
                    .eq(GroupsRelationAlert::getSkuId, sku.getId())
                    .eq(GroupsRelationAlert::getIsReset, false));
        }

        //HBO GO 满员，车队下架
        setDownIfFull(goodsDon, groupsTrips);

        //是否是GPT独立会员
        if (goodsDon.getId() == Constant.GPT_PLUS_GID && sku.getNum() == 1) {
            setRelationRechargeRemainNumInfo(groupsTrips.getId(), sku.getMonths(), account.getAccount(), account.getPassword());
        }
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void replaceTripsAccount(ReplaceTripsAccountReq req) {
        Long groupsId = req.getGroupsId();
        String account = req.getAccount().trim();
        String password = req.getPassword().trim();
        String remark = req.getRemark();
        Date afterStartTime = req.getStartTime();
        Date afterExpiryTime = req.getExpiryTime();
        GroupsAccountView groupsAccountView = beanSearcher.searchFirst(GroupsAccountView.class, MapUtils.builder()
                .field(GroupsAccountView::getGroupsId, groupsId)
                .build());
        if (groupsId == null) {
            throw BusinessRuntimeException.getInstance("车队已不存在");
        }
        Long accountId = groupsAccountView.getAccountId();
        if (accountId == null) {
            throw BusinessRuntimeException.getInstance("该车队暂未配置账号");
        }
        Long goodsId = groupsAccountView.getGoodsId();
        if (!account.contains("客服")) {
            if (accountCommonService.checkIsDupAccount(goodsId, account)) {
                throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
            }
        }
        //Claude3只允许替换一次
        if (Constant.CALUDE_GOODS_ID.equals(groupsAccountView.getGoodsId())) {
            Integer count = replaceRecordMapper.selectCount(Wrappers.lambdaQuery(GroupsTripsAccountReplaceRecord.class)
                    .eq(GroupsTripsAccountReplaceRecord::getGroupsId, groupsAccountView.getGroupsId()));
            if (count > 0) throw BusinessRuntimeException.getInstance("Claude3账号只允许替换一次");
        }
        if (afterStartTime == null) {
            afterStartTime = groupsAccountView.getStartTime();
        }
        if (afterExpiryTime == null) {
            afterExpiryTime = groupsAccountView.getExpiryTime();
        }
        log.info("原账号accountId:{}", accountId);
        //替换账号
        int update = accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
                .set(Account::getAccount, account)
                .set(Account::getPassword, password)
                .set(Account::getRemark, remark)
                .set(StrUtil.isNotBlank(req.getEmail()), Account::getEmail, req.getEmail())
                .set(StrUtil.isNotBlank(req.getRelateEmail()), Account::getRelateEmail, req.getRelateEmail())
                .set(Account::getStartTime, afterStartTime)
                .set(Account::getExpiryTime, afterExpiryTime)
                .set(Account::getGptRefreshToken, StrUtil.EMPTY)
                .eq(Account::getId, accountId));
        if (update == 0) {
            log.info("替换原账号oldAccount:{}至新账号newAccount:{}失败", groupsAccountView.getAccount(), account);
            throw BusinessRuntimeException.getInstance("替换账号失败");
        }

        if (StrUtil.isNotBlank(groupsAccountView.getGptRefreshToken())) {
            //清除gpt token
            redisService.del(RedisKey.CHATGPT_ACCESS_TOKEN + groupsAccountView.getAccount());
            redisService.del(RedisService.key.CHAT_GPT_TOKEN_EXCEPTION_KEY.getName() + groupsAccountView.getAccount());
        }

        //时间有效
        if (afterExpiryTime != null && afterExpiryTime.after(DateTime.now())) {
            groupsMapper.update(null, Wrappers.lambdaUpdate(GroupsTrips.class)
                    .set(GroupsTrips::getStatus, GroupsTrips.Status.validity)
                    .eq(GroupsTrips::getAccountId, accountId)
                    .eq(GroupsTrips::getStatus, GroupsTrips.Status.down));
        }

        //保存替换记录
        GroupsTripsAccountReplaceRecord replaceRecord = new GroupsTripsAccountReplaceRecord();
        replaceRecord.setGroupsId(groupsId);
        replaceRecord.setOldAccountId(accountId);
        replaceRecord.setOldAccount(groupsAccountView.getAccount());
        replaceRecord.setOldPassword(groupsAccountView.getPassword());
        replaceRecord.setOldStartTime(groupsAccountView.getStartTime());
        replaceRecord.setOldExpiryTime(groupsAccountView.getExpiryTime());

        Long adminId = req.getAdminId();
        Optional.ofNullable(cmsUserMapper.selectById(adminId)).ifPresent(admin -> replaceRecord.setOperator(admin.getNickname()));

        replaceRecord.setNewAccount(account);
        replaceRecord.setNewPassword(password);
        replaceRecord.setNewStartTime(afterStartTime);
        replaceRecord.setNewExpiryTime(afterExpiryTime);
        replaceRecord.setRemark(remark);

        replaceRecordMapper.insert(replaceRecord);

        TASK_EXECUTOR.execute(() -> sendChangeAccountMsg(groupsId, goodsId, account));;
    }

    @Override
    public Integer getAvailableRelation(Long goodsId, Long skuId) {
        //chatGPT
        GoodsDonSku sku = skuMapper.selectById(skuId);
        if (sku == null) {
            return BigDecimal.ZERO.intValue();
        }
        goodsId = sku.getGoodsId();
        Integer skuNum = sku.getNum();
        if (Constant.AI_goodsIds.contains(sku.getGoodsId()) && sku.getNum() > 1) {
            Integer extraNum = Constant.AI_EXTRACT_NUM;
            //GPT 4个月付
            if (skuId == 178l) {
                extraNum = 2;
            }
            Integer maxNum = skuNum + extraNum;
            //主账号有效时间
            DateTime time = DateUtil.offsetDay(DateUtil.beginOfDay(DateTime.now()), 25);
            Integer available = relationMapper.selectAvailableRelation(skuId, skuNum);
            //额外硬塞
            Integer special_available = relationMapper.selectSpecialGroupsRelationAvailable(skuId, maxNum, skuNum, extraNum, time);
            available += special_available;
            //GPT Plus 10人月付规格 4人月付
            if (Constant.GPT_PLUS_PARKING_SKU_IDS.contains(skuId)) {
                //上面已排除限制车队
                //限制车队可用车数位
                Integer limitAvailable = Optional.ofNullable(relationMapper.selectLimitAvailableNum(skuId, maxNum)).orElse(0);
                if (limitAvailable < 0) {
                    limitAvailable = 0;
                }
                available += limitAvailable;

                //新车队预备上车 最大可用数
                if (Constant.GPT_PLUS_PARKING_SKU_IDS.get(0).equals(skuId)) {
                    maxNum = 10;
                }else {
                    maxNum = 4;
                }
            }
            available = getAvailableAfterPreAccount(available, skuId, maxNum, goodsId);
            //待发车已有人员成功上车
            Integer waitingNum = relationMapper.selectNumWaitingGroups(skuId);
            available -= waitingNum;
            return available;
        }

        Integer available = relationMapper.selectAvailableRelation(skuId, skuNum);
        available = getAvailableAfterPreAccount(available, skuId, skuNum, goodsId);
        //待发车已有人员成功上车
        Integer waitingNum = relationMapper.selectNumWaitingGroups(skuId);
        available -= waitingNum;
        return available;
    }

    @Override
    public void sendChangeAccountMsg(Long groupsId, Long goodsId, String account) {
        GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
        String title = goodsDon != null ? goodsDon.getTitle() : "车票";
        DateTime now = DateTime.now();
        Boolean isPrd = envCommonService.isPrdEnv();
        List<GroupsRelationView> groupsRelations = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getGroupsId, groupsId).build());
        if (CollUtil.isEmpty(groupsRelations)) {
            return;
        }
        Long skuId = groupsMapper.selectById(groupsId).getSkuId();
        userSysMsgNotifyService.recordUserAccountUpdateSysMsg(goodsId, skuId, groupsRelations, account, goodsDon.getTitle());
        groupsRelations.forEach(relation -> {
            if (relation.getExpiryTime() == null) {
                return;
            }
            //账号有效期小于5天的人，不发账号替换/改密码短信提醒
            if (now.after(DateUtil.offsetDay(relation.getExpiryTime(), -5))) {
                return;
            }
            //去掉GPT过滤平台
            if (Constant.CHANGE_ACCOUNT_PWD_FILTER_GIDS.get(1) == goodsId) {
                return;
            }
            if (relation.getUserId() != 0 && isPrd && relation.getYhsId() == 0) {
                try {
                    smsService.sendSmsToRelationUser(relation.getUserId(), Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title, account);
                } catch (Exception e) {
                }
            }
        });
    }

    public Integer getAvailableAfterPreAccount(Integer available, Long skuId, Integer maxNum, Long goodsId) {
        MapBuilder builder = MapUtils.builder();
        if (goodsId == 26) {
            //是否在预备规格集合中
            String extra_sql = String.format("FIND_IN_SET(%s,a.pre_sku_ids) > 0", skuId);
            builder.put("extra_sql", extra_sql);
        }
        Number preAccount = beanSearcher.searchCount(AccountView.class, builder
                .field(AccountView::getGoodsId, goodsId)
                .field(AccountView::getAccountType, 2)
                .field(AccountView::getGroupsId).op(Operator.IsNull)
                .build());
        //计算上预发布账号车位数
        if (preAccount.intValue() > 0) {
            available += preAccount.intValue() * maxNum;
        }
        return available;
    }

    private void setDownIfFull(GoodsDon goodsDon, GroupsTrips groupsTrips) {
        //HBO GO 满员，车队下架
        if (goodsDon.getId() == Constant.HBO_GO_GOODS_ID) {
            if (groupsTrips.getStatus() == GroupsTrips.Status.validity) {
                Integer count2 = relationMapper.selectCount(Wrappers.lambdaQuery(GroupsRelation.class)
                        .eq(GroupsRelation::getGroupsId, groupsTrips.getId())
                        .in(GroupsRelation::getStatus, List.of(GroupsRelation.Status.none, GroupsRelation.Status.locking)));
                if (count2 == 0) {
                    log.info("HBO GO车队:{}已满员，自动下架", groupsTrips.getId());
                    groupsMapper.update(null, Wrappers.lambdaUpdate(GroupsTrips.class)
                            .set(GroupsTrips::getStatus, GroupsTrips.Status.down)
                            .eq(GroupsTrips::getId, groupsTrips.getId()));
                }
            }
        }
    }


    /**
     * 奈飞异常恢复车票
     */
    private NetflixUserAccountSubmitRecoverRecord updateRelationIfRecoverTicket(Boolean isRecover, GoodsDonSku sku, GroupsRelation relation) {
        if (isRecover != null && isRecover) {
            NetflixUserAccountSubmitRecoverRecord recoverRecord = netflixUserAccountSubmitRecoverRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class)
                    .eq(NetflixUserAccountSubmitRecoverRecord::getSkuId, sku.getId())
                    .eq(NetflixUserAccountSubmitRecoverRecord::getStatus, 0)
                    .orderByAsc(NetflixUserAccountSubmitRecoverRecord::getCreatedTime)
                    .last("limit 1"));
            if (recoverRecord != null) {
                relation.setUserId(recoverRecord.getUserId());
                relation.setStatus(GroupsRelation.Status.validity);
                relation.setStartTime(DateTime.now());
                relation.setExpiryTime(DateUtil.offsetDay(relation.getStartTime(), recoverRecord.getRemainDays().intValue()));
                //清除车票
                List<Long> userIdList = userBindRelationService.getRelationUserIdList(recoverRecord.getUserId(), null);
                GroupsRelation clearRelation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
                        .eq(GroupsRelation::getId, recoverRecord.getRelationId())
                        .in(GroupsRelation::getUserId, userIdList)
                        .last("limit 1"));
                if (clearRelation != null) {
                    clearService.clearTicket(clearRelation, UserTicketClearedRecord.Source.ticket_replace);
                }
                recoverRecord.setStatus(1);
                OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
                        .in(OrderDon::getUserId, userIdList)
                        .eq(OrderDon::getRelationId, recoverRecord.getRelationId())
                        .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
                        .orderByDesc(OrderDon::getId)
                        .last("limit 1"));
                if (orderDon != null) {
                    orderDon.setRelationId(relation.getId());
                    orderDonMapper.updateById(orderDon);
                }
                NetflixUserAccountStatusRecord netflixUserAccountStatusRecord = netflixUserAccountStatusRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class)
                        .in(NetflixUserAccountStatusRecord::getUserId, userIdList)
                        .eq(NetflixUserAccountStatusRecord::getRelationId, recoverRecord.getRelationId())
                        .eq(NetflixUserAccountStatusRecord::getDeleted, 1)
                        .last("limit 1"));
                if (netflixUserAccountStatusRecord != null) {
                    netflixUserAccountStatusRecord.setDeleted(false);
                    netflixUserAccountStatusRecordMapper.updateById(netflixUserAccountStatusRecord);
                }
                return recoverRecord;
            }
        }
        return null;
    }

    private void setRelationRechargeRemainNumInfo(Long groupsId, Integer addNum, String account, String password) {
        GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).eq(GroupsRelation::getGroupsId, groupsId).last("limit 1"));
        if (relation.getStatus() == GroupsRelation.Status.validity) {
            if (relation.getRechargeStatus() == null) {
                relation.setRechargeStatus(GroupsRelation.RechargeStatus.complete);
                relation.setRechargeNum(addNum);
                relation.setRechargeRemainNum(addNum - 1);
                relation.setSubmitTime(DateTime.now());
                relation.setSendTime(relation.getSubmitTime());
                relation.setAccount(account);
                relation.setPassword(password);
                relationMapper.updateById(relation);
                //记录gpt代充记录
                gptUserRechargeRecordService.recordGptUserRechargeNum(relation.getUserId(), relation.getId(), relation.getAccount(), relation.getRechargeRemainNum(), null, "下单");
            }
        }
    }
}
