package com.cyksj.service.chatgpt.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.constant.Constant;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.snowflake.Sequence;
import com.cyksj.common.util.Jsons;
import com.cyksj.common.util.SmsUtil;
import com.cyksj.common.util.StringUtil;
import com.cyksj.dto.RedisKey;
import com.cyksj.mapper.*;
import com.cyksj.mapper.station.CollegeStudentStationUseTicketRecordMapper;
import com.cyksj.model.dto.ChatgptUserVerifyDto;
import com.cyksj.model.entity.*;
import com.cyksj.model.views.ChatGptUserView;
import com.cyksj.model.views.ChatgptCarInfoView;
import com.cyksj.redis.RedisService;
import com.cyksj.service.chatgpt.ChatGptAccountService;
import com.cyksj.service.sys.SysConfigService;
import com.cyksj.service.user.UserBindRelationService;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.SearchResult;
import com.ejlchina.searcher.util.MapUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.stream.FileImageOutputStream;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author chan
 * @date 2024/3/19 11:01
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ChatGptAccountServiceImpl implements ChatGptAccountService {

    @Value("${chatgpt.domain}")
    private String GPT_DOMAIN;

    @Value("${chatgpt.car.domain}")
    private String CAR_GPT_DOMAIN;

    private static final String GPT_PROXY = "https://chat-chan-87jztgkf257d.xyhelper.org";

    private static final String RESTRICTION_URL = "https://nf.video/bind/web/validating";

    private final static Sequence SEQUENCE = new Sequence(0);

    private final RedisService redisService;

    private final ChatgptUserMapper chatgptUserMapper;

    private final ChatgptSessionMapper chatgptSessionMapper;

    private final GroupsRelationMapper groupsRelationMapper;

    private final GroupsMapper groupsMapper;

    private final GoodsDonSkuMapper skuMapper;

    private final UserMapper userMapper;

    private final UserBindRelationService userBindRelationService;

    private final AccountMapper accountMapper;

    private final BeanSearcher beanSearcher;

    private final ChatgptUserTokenPrepareMapper chatgptUserTokenPrepareMapper;

    private final CollegeStudentStationUseTicketRecordMapper collegeStudentStationUseTicketRecordMapper;

    private final UpgradePackageMapper upgradePackageMapper;

    private final OrderDonMapper orderDonMapper;

    private final SysConfigService sysConfigService;

    private final HttpServletRequest request;

    private final ChatgptTrialRecordMapper chatgptTrialRecordMapper;

    private final ChatgptUserRestrictionMapper chatgptUserRestrictionMapper;

    private final MidjourneyUserMapper midjourneyUserMapper;

    private final ClaudeUserMapper claudeUserMapper;

    private final LumaUserMapper lumaUserMapper;

    private final GrokUserMapper grokUserMapper;

    @Override
    public String getGptSession(String account, String password) {
        String officialSession = "";
        try {
            Account at = new Account();
            at.setAccount(account);
            at.setPassword(password);
            JSONObject loginResult = getLoginResult(at);
            String str = loginResult.getStr("detail");
            if (StringUtils.isNotBlank(str)) {
                throw BusinessRuntimeException.getInstance("登录获取token错误 error:" + str);
            }
            officialSession = loginResult.toString();
        } catch (Exception e) {
            throw BusinessRuntimeException.getInstance("登录获取token错误 error:" + e.getMessage());
        }
        return officialSession;
    }

    @Override
    public void clearGptNum(Long relationId) throws Exception {
        HttpRequest request = new HttpRequest("https://saas.galaxyva.com/cleanUserTokenLimit?relationId=" + relationId);
        HttpResponse execute = request.method(Method.GET).setConnectionTimeout(3000).timeout(3000).execute();
        String body = execute.body();
        JSONObject re = Jsons.parseObject(body, JSONObject.class);
        if (!body.contains("成功")) {
            throw BusinessRuntimeException.getInstance(re.getStr("message"));
        }
    }

    @Override
    public void gptSwitchModel(long userId, Long relationId) {
        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
        Integer count = groupsRelationMapper.selectCount(Wrappers.lambdaQuery(GroupsRelation.class)
                .in(GroupsRelation::getUserId, userIdList)
                .eq(GroupsRelation::getId, relationId));
        if (count > 0) {
            Optional.ofNullable(chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
                    .eq(ChatgptUser::getRelationId, relationId)
                    .last("limit 1"))).ifPresent(cu -> {
                cu.setModel(cu.getModel() == 0 ? 1 : 0);
                chatgptUserMapper.updateById(cu);
            });
        }
    }

    /**
     * 获取登录结果
     *
     * @param account
     * @return
     * @throws Exception
     */
    private JSONObject getLoginResult(Account account) throws Exception {
        HttpRequest request = new HttpRequest(GPT_PROXY + "/applelogin");
        request.form("username", account.getAccount());
        request.form("password", account.getPassword());
        request.header("Content-Type", "application/x-www-form-urlencoded");
        request.header("X-Requested-With", "xyhelper");
        HttpResponse execute = request.method(Method.POST).execute();
        String body = execute.body();
        log.info("登录返回token res:{}", body);
        return new JSONObject(body);
    }


    /**
     * 获取登录url
     *
     * @param userId
     * @param relationId
     * @return
     */
    @Override
    public String getLoginUrl(Long userId, Long relationId) {
        GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
        GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
        GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
        log.info("用户:{},所在车次:{},座位id:{},在{}获取跳转GPT镜像的登录url", userId, groupsTrips.getId(), relationId, DateTime.now());

        if (goodsDonSku != null && goodsDonSku.getIsMirror()) {
            ChatgptUser chatgptUser = getChatgptUser(userId, relationId, groupsRelation, groupsTrips, goodsDonSku);
            if (214610L == relationId) {
                return "https://cdn.galaxydvd.com/login_token?access_token=" + chatgptUser.getUserToken();
            }
            return GPT_DOMAIN + "/login_token?access_token=" + chatgptUser.getUserToken();
        } else {
            throw BusinessRuntimeException.getInstance("服务器出了点问题");
        }
    }

    /**
     * 获取车队登录url
     *
     * @param userId
     * @param carId
     * @return
     */
    @Override
    public String getCarLoginUrl(String domain, Long userId, Long relationId, String carId) {
        GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
        GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
        GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
        if (goodsDonSku != null && goodsDonSku.getIsMirror() && goodsDonSku.getIsCar()) {
            ChatgptUser chatgptUser = getChatgptCarUser(userId, relationId, groupsRelation, goodsDonSku);
            String DOMAIN = getGptDomain(domain, goodsDonSku);
            log.info("domain:{}，用户:{},所在车次:{},座位id:{},在{}获取跳转GPT镜像的登录url", DOMAIN, userId, groupsTrips.getId(), relationId, DateTime.now());
            //另外一版镜像gpt
            SysConfig gptNewDomain = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
                    .eq(SysConfig::getSysKey, "mirror_gpt_new_domain")
                    .last("limit 1"));
            Boolean isNewGptDomain = false;
            if (gptNewDomain != null) {
                String sysValue = gptNewDomain.getSysValue();
                if (JSONUtil.isJsonArray(sysValue)) {
                    List<String> domainList = JSONUtil.parseArray(sysValue).toList(String.class);
                    if (domainList.contains(DOMAIN)) {
                        isNewGptDomain = true;
                    }
                }
            }
            return DOMAIN + (isNewGptDomain || DOMAIN.equals("https://gpt.bestaistore.com") || DOMAIN.equals("https://oai.liuliangbang.vip") ? "/codetoken?logintoken=" + chatgptUser.getUserToken() : "/auth/logintoken?carid=" + carId + "&usertoken=" + chatgptUser.getUserToken() );
        } else {
            throw BusinessRuntimeException.getInstance("服务器出了点问题");
        }
    }

    /**
     * 根据userToken获取车队登录url
     */
    @Override
    public String getCarLoginUrlWithToken(String domain, String userToken, String carId) {
        ChatgptUser chatgptUser = getCarChatGptUserWithToken(userToken);
        if (chatgptUser != null) {
            ChatgptUserTokenPrepare chatgptUserTokenPrepare = chatgptUserTokenPrepareMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserTokenPrepare.class)
                    .eq(ChatgptUserTokenPrepare::getUserToken, userToken)
                    .last("limit 1"));
            Long skuId = chatgptUserTokenPrepare.getSkuId();
            GoodsDonSku goodsDonSku = skuMapper.selectById(skuId);
            String DOMAIN = getGptDomain(domain, goodsDonSku);
            log.info("domain:{}，渠道用户:{},在{}获取跳转GPT镜像的登录url", DOMAIN, userToken, DateTime.now());
            return DOMAIN + "/auth/logintoken?carid=" + carId + "&usertoken=" + chatgptUser.getUserToken();
        } else {
            throw BusinessRuntimeException.getInstance("服务出了点问题");
        }
    }

    /**
     * 获取车位信息
     *
     * @param userId
     * @param relationId
     * @return
     */
    private GroupsRelation getGroupsRelation(Long userId, Long relationId) {
        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
        GroupsRelation groupsRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).in(GroupsRelation::getUserId, userIdList).eq(GroupsRelation::getId, relationId));
        if (groupsRelation == null) {
            throw BusinessRuntimeException.getInstance("车票不存在");
        }
        return groupsRelation;
    }

    /**
     * 获取车队信息
     *
     * @param groupsRelation
     * @return
     */
    private GroupsTrips getGroupsTrips(GroupsRelation groupsRelation) {
        GroupsTrips groupsTrips = groupsMapper.selectById(groupsRelation.getGroupsId());
        if (groupsTrips == null) {
            throw BusinessRuntimeException.getInstance("车队异常");
        }
        return groupsTrips;
    }

    private ChatgptUser getChatgptUser(Long userId, Long relationId, GroupsRelation groupsRelation, GroupsTrips groupsTrips, GoodsDonSku goodsDonSku) {
        ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getRelationId, relationId));
        User user = userMapper.selectById(userId);
        if (chatgptUser == null) {
            chatgptUser = createChatgptUser(groupsRelation, groupsTrips, user, goodsDonSku);
        } else {
            updateChatgptUser(groupsRelation, user, chatgptUser);
        }
        return chatgptUser;
    }

    private ChatgptUser getChatgptCarUser(Long userId, Long relationId, GroupsRelation groupsRelation, GoodsDonSku goodsDonSku) {
        ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getRelationId, relationId));
        User user = userMapper.selectById(userId);
        if (chatgptUser == null) {
            chatgptUser = createChatgptUser(groupsRelation, null, user, goodsDonSku);
        } else {
            updateChatgptUser(groupsRelation, user, chatgptUser);
        }
        return chatgptUser;
    }

    /**
     * 创建chatgptUser
     */
    private synchronized ChatgptUser createChatgptUser(GroupsRelation groupsRelation, GroupsTrips groupsTrips, User user, GoodsDonSku goodsDonSku) {
        ChatgptUser chatgptUser = new ChatgptUser();
        if (goodsDonSku.getIsCar()) {
            chatgptUser.setIsCar(true);
            chatgptUser.setLimitNum(goodsDonSku.getGptLimitNum());
            chatgptUser.setLimitTime(goodsDonSku.getGptLimitTime());
            chatgptUser.setDsLimitTime(goodsDonSku.getDsLimitTime());
            chatgptUser.setDsLimitNum(goodsDonSku.getDsLimitNum());
            chatgptUser.setOtherLimitNum(goodsDonSku.getOtherLimitNum());
            chatgptUser.setOtherLimitTime(goodsDonSku.getOtherLimitTime());
        }
        try {
            chatgptUser.setExpireTime(groupsRelation.getExpiryTime());
            chatgptUser.setIsPlus(1);
            chatgptUser.setName(user.getNickname());
            chatgptUser.setImg(getWxImg(user.getHeadimgurl(), user));
            chatgptUser.setRelationId(groupsRelation.getId());
            chatgptUser.setUserToken(UUID.randomUUID().toString());
            chatgptUserMapper.insert(chatgptUser);

            //是否是大学生限时车队
            Date expiryTime = groupsRelation.getExpiryTime();
            Date startTime = groupsRelation.getStartTime();
            //大学生站 1天免费试用
            if (DateUtil.between(startTime, expiryTime, DateUnit.DAY) <= 1) {
                CollegeStudentStationUseTicketRecord useTicketRecord = new CollegeStudentStationUseTicketRecord();
                useTicketRecord.setUserId(user.getId());
                useTicketRecord.setUserToken(chatgptUser.getUserToken());
                collegeStudentStationUseTicketRecordMapper.insert(useTicketRecord);
            }
        } catch (DuplicateKeyException e) {
            log.error("重复插入镜像用户:{}token,errmsg:{}", user.getNickname(), StringUtil.getErrorText(e));
        }
        return chatgptUser;
    }

    /**
     * 创建chatgptUser 无需车队
     */
    public ChatgptUser generateChatGptUserUnderPrepare(ChatgptUserTokenPrepare prepare) {
        ChatgptUser chatgptUser = new ChatgptUser();
        GoodsDonSku goodsDonSku = skuMapper.selectById(prepare.getSkuId());
        if (goodsDonSku == null) {
            throw BusinessRuntimeException.getInstance("车队规格不存在,请联系客服..");
        }
        if (goodsDonSku.getIsCar()) {
            chatgptUser.setIsCar(true);
            chatgptUser.setLimitNum(goodsDonSku.getGptLimitNum());
            chatgptUser.setLimitTime(goodsDonSku.getGptLimitTime());
            chatgptUser.setDsLimitNum(goodsDonSku.getDsLimitNum());
            chatgptUser.setDsLimitTime(goodsDonSku.getDsLimitTime());
            chatgptUser.setOtherLimitNum(goodsDonSku.getOtherLimitNum());
            chatgptUser.setOtherLimitTime(goodsDonSku.getOtherLimitTime());
        }
        try {
            chatgptUser.setExpireTime(DateUtil.offsetMonth(DateTime.now(), goodsDonSku.getMonths()));
            chatgptUser.setIsPlus(1);
            chatgptUser.setName(prepare.getName());
            chatgptUser.setImg(prepare.getImg());
            chatgptUser.setUserToken(prepare.getUserToken());
            chatgptUserMapper.insert(chatgptUser);

            prepare.setStatus(true);
            chatgptUserTokenPrepareMapper.updateById(prepare);
            log.info("用户激活userToken:{}成功", prepare.getUserToken());
        } catch (DuplicateKeyException e) {
            log.error("重复插入镜像车队用户:{}token,errmsg:{}" + chatgptUser.getId(), StringUtil.getErrorText(e));
        }
        return chatgptUser;
    }

    private void updateChatgptUser(GroupsRelation groupsRelation, User user, ChatgptUser chatgptUser) {
        chatgptUserMapper.update(null, Wrappers.lambdaUpdate(ChatgptUser.class)
                .set(ChatgptUser::getName, user.getNickname())
                .set(ChatgptUser::getImg, getWxImg(user.getHeadimgurl(), user))
                .set(ChatgptUser::getExpireTime, groupsRelation.getExpiryTime())
                .eq(ChatgptUser::getId, chatgptUser.getId())
                .eq(ChatgptUser::getRelationId, chatgptUser.getRelationId()));
    }

    /**
     * 更换wx头像至oss
     */
    private String getWxImg(String headimgurl, User user) {
        if (headimgurl.contains("thirdwx.qlogo.cn")) {
            try {
                byte[] body = HttpUtil.downloadBytes(headimgurl);
                Path tempFile = Files.createTempFile("wxheadimg-" + user.getId(), ".jpeg");
                try (FileImageOutputStream imageOutput = new FileImageOutputStream(tempFile.toFile())) {
                    imageOutput.write(body, 0, body.length);
                }
                Map<String, Object> paramMap = new HashMap<>();
                paramMap.put("file", tempFile.toFile());
                JSONObject result = JSONUtil.parseObj(HttpUtil.post("https://files.liuliangbang.vip/pic/ups", paramMap));
                FileUtil.del(tempFile);
                return result.getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl");
            } catch (Exception ex) {
                log.error("上传微信头像错误！msg:{}", StringUtil.getErrorText(ex));
                return "./avatars.png";
            }
        } else {
            return user.getHeadimgurl();
        }
    }

    @Override
    public ChatgptUser findByUserTokenAndExpireTimeAfter(String userToken, LocalDateTime now) {
        return chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getUserToken, userToken).gt(ChatgptUser::getExpireTime, now));
    }



    /**
     * 获取指定用户ID在滑动窗口内的提问次数
     *
     * @param userToken 用户token
     * @return 滑动窗口内的请求次数
     */
    @Override
    public Long getConversationCount(String userToken, Long limitTime) {
        try {
            String res = HttpUtil.get("http://154.198.213.52:9611/getConversationCount?userToken=" + userToken);
            return new JSONObject(res).getLong("count");
        }catch (Exception e){
            return 0L;
        }
    }

    public JSONObject getConversationCount(String userToken) {
        try {
            String res = HttpUtil.get("https://saas.galaxyva.com/getConversationCount?userToken=" + userToken, 5000);
            return new JSONObject(res);
        }catch (Exception e){
            return new JSONObject("{\"count\": 0,\"o1_mini\": 0,\"o1_p\": 0}");
        }
    }


    @Override
    public ChatgptSession checkSession(String carId) {
        ChatgptSession chatgptSession = chatgptSessionMapper.selectOne(Wrappers.lambdaQuery(ChatgptSession.class).eq(ChatgptSession::getCarId, carId).eq(ChatgptSession::getIsCar, true).last(" limit 1"));
        if (chatgptSession == null) {
            throw BusinessRuntimeException.getInstance("车队不存在");
        }
        return chatgptSession;
    }


    private Long carOaiLimit(String carId, Boolean isTeam) {
        if(isTeam && redisService.hasKey("chatgpt:team:clears_in:" + carId)){
            return redisService.getExpire("chatgpt:team:clears_in:" + carId);
        }
        if (redisService.hasKey("chatgpt:clears_in:" + carId)) {
            return redisService.getExpire("chatgpt:clears_in:" + carId);
        }
        return 0L;
    }


    @Override
    public Boolean checkCarAccount(long userId, Long relationId) {
        GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
        GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
        GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());

        if (goodsDonSku != null && goodsDonSku.getGoodsId() == 18 && goodsDonSku.getIsMirror() && goodsDonSku.getIsCar()) {
            ChatgptUser chatgptUser = getChatgptCarUser(userId, relationId, groupsRelation, goodsDonSku);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public Boolean checkCarAccountWithToken(String userToken) {

        ChatgptUser chatgptUser = getCarChatGptUserWithToken(userToken);

        return chatgptUser != null;

    }

    @Override
    public ChatgptUser getCarChatGptUser(long userId, Long relationId) {
        GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
        GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
        GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());

        if (goodsDonSku != null && goodsDonSku.getIsMirror() && goodsDonSku.getIsCar()) {
            return getChatgptCarUser(userId, relationId, groupsRelation, goodsDonSku);
        }
        return null;
    }

    @Override
    public ChatgptUser getCarChatGptUserWithToken(String userToken) {
        ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getUserToken, userToken).last(" limit 1"));
        if (chatgptUser == null) {
            //是否是用户token预备账号
            ChatgptUserTokenPrepare chatgptUserTokenPrepare = chatgptUserTokenPrepareMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserTokenPrepare.class)
                    .eq(ChatgptUserTokenPrepare::getUserToken, userToken).last("limit 1"));
            if (chatgptUserTokenPrepare != null) {
                chatgptUser = generateChatGptUserUnderPrepare(chatgptUserTokenPrepare);
            }
        }
        if (chatgptUser != null) {
            if(!chatgptUser.getIsCar()){
                throw BusinessRuntimeException.getInstance("您非车队用户，请购买车队套餐");
            }
            if (chatgptUser.getRelationId() != null) {
                throw BusinessRuntimeException.getInstance("非渠道用户，请通过官网登录!");
            }
            return chatgptUser;
        }
        return null;
    }

    /**
     * 获取车队分页信息
     */
    @Override
    public SearchResult<ChatgptCarInfoView> getCarInfoPage(String userToken, Integer limit) {

        SearchResult<ChatgptCarInfoView> chatgptCarInfoViews = beanSearcher.search(ChatgptCarInfoView.class, MapUtils.flatBuilder(request.getParameterMap())
                .orderBy(ChatgptCarInfoView::getSort).asc()
                .orderBy(ChatgptCarInfoView::getTeamClearsIn).asc()
                .orderBy(ChatgptCarInfoView::getClearsIn).asc().orderBy(ChatgptCarInfoView::getScore).asc().build());

        if (chatgptCarInfoViews != null) {
            chatgptCarInfoViews.getDataList().forEach(this::buildChatgptCarInfoView);
        }
        return chatgptCarInfoViews;
    }

    /**
     * 获取车队信息
     */
    @Override
    public List<ChatgptCarInfoView> getCarInfoList(String userToken, Integer limit, Boolean isPlus) {
        List<ChatgptCarInfoView> lowestScoreFleets = getLowestScoreFleets(limit, isPlus);
        return lowestScoreFleets;
    }



    // 获取得分最低的N个车队的方法
    public List<ChatgptCarInfoView> getLowestScoreFleets(int count, Boolean isPlus) {
        List<ChatgptCarInfoView> chatgptCarInfoViews = beanSearcher.searchList(ChatgptCarInfoView.class, MapUtils.builder().field(ChatgptCarInfoView::getIsPlus, isPlus).orderBy(ChatgptCarInfoView::getScore).asc().limit(0, count).build());

        chatgptCarInfoViews.forEach(this::buildChatgptCarInfoView);
        return chatgptCarInfoViews;
    }


    // 构建ChatgptCarInfoView对象
    private ChatgptCarInfoView buildChatgptCarInfoView(ChatgptCarInfoView view) {
        // 在这里根据carId获取相关信息并填充到ChatgptCarInfoView对象中

        view.setStatus(view.getScore() >= 100 ? "繁忙" : "空闲"); // 或“繁忙”

        if(view.getCarName().contains("T")){
            view.setType("Team");
            Long team = view.getTeamClearsIn();
            if (team != 0L) {
                view.setTeamExpTime(new DateTime(System.currentTimeMillis() + team * 1000));
            }
            Long aLong = view.getClearsIn();
            if (aLong != 0L) {
                view.setExpTime(new DateTime(System.currentTimeMillis() + aLong * 1000));
            }
            if (view.getExpTime() != null && view.getTeamExpTime() != null) {
                view.setStatus("全部停运");
            }else if(view.getExpTime() != null || view.getTeamExpTime() != null) {
                view.setStatus("部分停运");
            }
        }else {
            view.setType("Plus");
            Long aLong = view.getClearsIn();
            if (aLong != 0L) {
                view.setStatus("停运");
                view.setExpTime(new DateTime(System.currentTimeMillis() + aLong * 1000));
            }
        }
        view.setScore(Math.min(BigDecimal.valueOf(view.getScore()).multiply(BigDecimal.valueOf(0.5)).setScale(0, RoundingMode.DOWN).doubleValue(), 200));
        return view;
    }

    @Override
    public ChatGptUserView getUserInfo(long userId, Long relationId) {
        if (checkCarAccount(userId, relationId)) {
            GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
            GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
            GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
            ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getRelationId, relationId));

            Integer count = upgradePackageMapper.selectCount(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + groupsTrips.getSkuId() + "\"')")
                    .gt(UpgradePackage::getNum, chatgptUser.getLimitNum())
                    .eq(UpgradePackage::getStatus, Boolean.TRUE)
                    .eq(UpgradePackage::getGptType, 0)
                    .eq(UpgradePackage::getDeleted, Boolean.TRUE));
            Boolean upgrade = count > 0 ? true : false;
            OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
                    .eq(OrderDon::getRelationId, relationId)
                    .eq(OrderDon::getUserId, groupsRelation.getUserId())
                    .eq(OrderDon::getOrderType, 1)
                    .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
                    .orderByDesc(OrderDon::getId)
                    .last("limit 1"));
            Long orderId = null;
            if (orderDon != null) {
                orderId = orderDon.getId();
            }
            BigDecimal packagePrice = null;
            if (chatgptUser.getPackageId() != 0) {
                UpgradePackage upgradePackage = upgradePackageMapper.selectById(chatgptUser.getPackageId());
                packagePrice = upgradePackage.getPrice();
            }
            JSONObject conversationCount = getConversationCount(chatgptUser.getUserToken());

            ChatGptUserView view = ChatGptUserView.builder()
                    .skuName(goodsDonSku.getSubTitle())
                    .specVal(goodsDonSku.getSpecVal())
                    .expireTime(chatgptUser.getExpireTime())
                    .limitNum(chatgptUser.getLimitNum())
                    .limitTime(chatgptUser.getLimitTime())
                    .dsLimitNum(chatgptUser.getDsLimitNum())
                    .dsLimitTime(chatgptUser.getDsLimitTime())
                    .otherLimitNum(chatgptUser.getOtherLimitNum())
                    .otherLimitTime(chatgptUser.getOtherLimitTime())
                    .upgrade(upgrade)
                    .orderId(orderId)
                    .goodsId(goodsDonSku.getGoodsId())
                    .skuId(goodsDonSku.getId())
                    .months(goodsDonSku.getMonths())
                    .use(Math.min(chatgptUser.getLimitNum(), Optional.ofNullable(conversationCount.getLong("count")).orElse(0L)))
                    .packageId(chatgptUser.getPackageId())
                    .packagePrice(packagePrice)
                    .isRenewPackage(chatgptUser.getRenewOrderId() != null ? true : false)
                    .renewSkuId(chatgptUser.getRenewSkuId())
                    .renewOrderId(chatgptUser.getRenewOrderId())
                    .model(chatgptUser.getModel())
                    .userToken(chatgptUser.getUserToken())
                    .build();
            if (view.getRenewSkuId() != null) {
                Optional.ofNullable(skuMapper.selectById(view.getRenewSkuId())).ifPresent(renewSuu -> view.setRenewSpecVal(renewSuu.getSpecVal()));
            }
            view.setOtherUse(Optional.ofNullable(conversationCount.getLong("other")).orElse(0L));
            view.setDpsUse(Optional.ofNullable(conversationCount.getLong("dps")).orElse(0L));
            return view;
        } else {
            throw BusinessRuntimeException.getInstance("您还未购买该车票");
        }
    }

    @Override
    public ChatGptUserView getUserInfoWithToken(String userToken) {
        if (checkCarAccountWithToken(userToken)) {
            ChatgptUser chatgptUser = getCarChatGptUserWithToken(userToken);
            return ChatGptUserView.builder()
                    .skuName("")
                    .expireTime(chatgptUser.getExpireTime())
                    .limitNum(chatgptUser.getLimitNum())
                    .limitTime(chatgptUser.getLimitTime())
                    .dsLimitNum(chatgptUser.getDsLimitNum())
                    .dsLimitTime(chatgptUser.getDsLimitTime())
                    .otherLimitNum(chatgptUser.getOtherLimitNum())
                    .otherLimitTime(chatgptUser.getOtherLimitTime())
                    .use(getConversationCount(chatgptUser.getUserToken(), chatgptUser.getLimitTime()))
                    .build();
        } else {
            throw BusinessRuntimeException.getInstance("您还未购买该车票");
        }
    }

    public String getGptDomain(String domain, GoodsDonSku goodsDonSku) {
        String DOMAIN = domain;
        if (StrUtil.isEmpty(DOMAIN)) {
            DOMAIN = "https://chat.galaxydvd.com";
            try {
                SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, goodsDonSku != null && goodsDonSku.getId() == 444 ? "zhihu_gpt_domain" : "mirror_gpt_domain"));
                if (sysConfig != null) {
                    String sysValue = sysConfig.getSysValue();
                    if (JSONUtil.isJsonArray(sysValue)) {
                        List<String> domainList = JSONUtil.parseArray(sysValue).toList(String.class);
                        DOMAIN = domainList.get(RandomUtil.randomInt(domainList.size()));
                    }
                }
            } catch (Exception e) {
                log.error("随机抽取域名错误. msg:{}", StringUtil.getErrorText(e));
            }
        }
        return DOMAIN;
    }

    @Override
    public String isRestrictions(String userToken, String referer, String userAgent) {
        //从redis 中查询该usertoken 当日使用次数
        DateTime now = DateTime.now();
        DateTime dateTime = DateUtil.beginOfDay(now.toJdkDate());
        DateTime endOfDayTime = DateUtil.endOfDay(now.toJdkDate());
        DateTime twelveHoursAgo = DateUtil.offset(now, DateField.HOUR, -6);
        ChatgptUserRestriction chatgptUserRestriction = chatgptUserRestrictionMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserRestriction.class)
                .eq(ChatgptUserRestriction::getUserToken, userToken)
                .ge(ChatgptUserRestriction::getCreatedTime, twelveHoursAgo.toString()).eq(ChatgptUserRestriction::getSuccess, false).last(" limit 1"));
        if (chatgptUserRestriction != null) {
            JSONObject result = new JSONObject();
            result.putOpt("url",chatgptUserRestriction.getUrl());
            result.putOpt("code",1);
            return result.toString();
        }
        String numStr = redisService.getStr(RedisKey.CHATGPT_USER_RESTRICTION + userToken);
        if (StringUtils.isNotBlank(numStr) && StringUtils.isNumeric(numStr)) {
            long num = Long.parseLong(numStr);
            if (num >= 150) {
                //触发限制，需要人机验证
                Integer count = chatgptUserRestrictionMapper.selectCount(Wrappers.lambdaQuery(ChatgptUserRestriction.class).eq(ChatgptUserRestriction::getUserToken, userToken)
                        .ge(ChatgptUserRestriction::getCreatedTime, dateTime.toString()));
                if (count > 10) {
                    chatgptUserMapper.update(null, Wrappers.lambdaUpdate(ChatgptUser.class).eq(ChatgptUser::getUserToken, userToken).set(ChatgptUser::getIsBlock, 1));
                }
                ChatgptUserRestriction restriction = new ChatgptUserRestriction();

                restriction.setRestrictionId(SEQUENCE.nextId().toString());
                restriction.setUrl(RESTRICTION_URL + "?restrictionId=" + restriction.getRestrictionId() + "&userToken=" + userToken);
                restriction.setUserToken(userToken);
                restriction.setUserAgent(userAgent);
                restriction.setReferer(referer);
                chatgptUserRestrictionMapper.insert(restriction);
                JSONObject result = new JSONObject();
                result.putOpt("url",restriction.getUrl());
                result.putOpt("code",1);
                return result.toString();
            }
        }
        JSONObject result = new JSONObject();
        result.putOpt("code",0);
        redisService.incr(RedisKey.CHATGPT_USER_RESTRICTION + userToken, 1L);
        long between = DateUtil.between(now, endOfDayTime, DateUnit.SECOND, true);
        redisService.expire(RedisKey.CHATGPT_USER_RESTRICTION + userToken, between);
        return result.toString();
    }

    @Override
    public Boolean gptRestrictionStatus(String userToken, String restrictionId) {
        ChatgptUserRestriction chatgptUserRestriction = chatgptUserRestrictionMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserRestriction.class)
                .eq(ChatgptUserRestriction::getUserToken, userToken)
                .eq(ChatgptUserRestriction::getRestrictionId, restrictionId)
                .last(" limit 1"));
        if (chatgptUserRestriction == null) {
            throw BusinessRuntimeException.getInstance("该验证异常.");
        }else {
            return chatgptUserRestriction.getSuccess();
        }
    }

    @Override
    public Boolean verifyRestriction(ChatgptUserVerifyDto chatgptUserVerifyDto) {
        SmsUtil.checkTencentCaptcha(chatgptUserVerifyDto.getTicket(), chatgptUserVerifyDto.getIp(), chatgptUserVerifyDto.getRandStr());
        // 清除一定次数，以及修改验证状态
        ChatgptUserRestriction chatgptUserRestriction = chatgptUserRestrictionMapper.selectOne(Wrappers.lambdaQuery(ChatgptUserRestriction.class)
                .eq(ChatgptUserRestriction::getUserToken, chatgptUserVerifyDto.getUserToken())
                .eq(ChatgptUserRestriction::getRestrictionId, chatgptUserVerifyDto.getRestrictionId())
                .eq(ChatgptUserRestriction::getSuccess, false)
                .last(" limit 1"));
        if (chatgptUserRestriction != null) {
            chatgptUserRestriction.setSuccess(true);
            chatgptUserRestriction.setVerifyUserAgent(chatgptUserVerifyDto.getUserAgent());
            chatgptUserRestriction.setSuccessTime(new Date());
            chatgptUserRestrictionMapper.updateById(chatgptUserRestriction);
            redisService.decr(RedisKey.CHATGPT_USER_RESTRICTION + chatgptUserVerifyDto.getUserToken(), 50L);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String trialGpt(String clientIP, String trialToken, String userAgent) {

        if (StringUtils.isNotBlank(trialToken)) {
            ChatgptTrialRecord chatgptTrialRecord = chatgptTrialRecordMapper.selectOne(Wrappers.lambdaQuery(ChatgptTrialRecord.class).eq(ChatgptTrialRecord::getUserToken, trialToken).last(" limit 1"));
            if (chatgptTrialRecord != null) {
                ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class).eq(ChatgptUser::getUserToken, trialToken));
                if (chatgptUser == null) {
                    return "";
                }else {
                    return chatgptUser.getUserToken();
                }
            }else {
                ChatgptUser chatgptUser = createTrialUser(clientIP);
                if(StringUtils.isBlank(chatgptUser.getUserToken())){
                    return "";
                }
                chatgptTrialRecord = new ChatgptTrialRecord();
                chatgptTrialRecord.setIp(clientIP);
                chatgptTrialRecord.setUserToken(chatgptUser.getUserToken());
                chatgptTrialRecordMapper.insert(chatgptTrialRecord);
                return chatgptUser.getUserToken();
            }
        }

        ChatgptUser chatgptUser = createTrialUser(clientIP);
        if(StringUtils.isBlank(chatgptUser.getUserToken())){
            return "";
        }
        ChatgptTrialRecord chatgptTrialRecord = new ChatgptTrialRecord();
        chatgptTrialRecord.setIp(clientIP);
        chatgptTrialRecord.setUserToken(chatgptUser.getUserToken());
        chatgptTrialRecordMapper.insert(chatgptTrialRecord);
        return chatgptUser.getUserToken();
    }

    @Override
    public JSONObject getGptUseInfo(String userToken) {
        ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
                .eq(ChatgptUser::getUserToken, userToken)
                .last("limit 1"));
        if (chatgptUser == null) {
            throw BusinessRuntimeException.getInstance("车票不存在");
        }
        Long relationId = chatgptUser.getRelationId();
        GroupsRelation relation = groupsRelationMapper.selectById(relationId);
        if (relation == null) {
            throw BusinessRuntimeException.getInstance("车票不存在");
        }
        try {
            String res = HttpUtil.get(String.format("https://image.yhlxj.com/api/getCount?usertoken=%s&limit=%s&time=%s&isVip=%s", userToken, chatgptUser.getLimitNum(), chatgptUser.getLimitTime(), relation.getIsVip()), 5000);
            return new JSONObject(res);
        }catch (Exception e){
            return new JSONObject("{\"count\": 0,\"o1_mini\": 0,\"o1_p\": 0}");
        }
    }

    @Override
    public String getMirrorToken(long userId, Long relationId) {
        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
        GroupsRelation relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
                .eq(GroupsRelation::getId, relationId)
                .gt(GroupsRelation::getExpiryTime, DateTime.now())
                .in(GroupsRelation::getUserId, userIdList)
                .last("limit 1"));
        if (relation == null) {
            throw BusinessRuntimeException.getInstance("车票不存在");
        }
        GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
        GoodsDonSku sku = skuMapper.selectById(groupsTrips.getSkuId());
        Long goodsId = sku.getGoodsId();
        if (goodsId == Constant.MJ_GID) {
            MidjourneyUser user = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
                    .eq(MidjourneyUser::getRelationId, relationId)
                    .last("limit 1"));
            if (user != null) {
                return user.getUserToken();
            }
        }
        if (goodsId == Constant.GPT_PLUS_GID) {
            ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
                    .eq(ChatgptUser::getRelationId, relationId)
                    .last("limit 1"));
            if (chatgptUser != null) {
                chatgptUser.setExpireTime(relation.getExpiryTime());
                chatgptUserMapper.updateById(chatgptUser);
                return chatgptUser.getUserToken();
            }
        }
        if (goodsId == Constant.CALUDE_GOODS_ID) {
            ClaudeUser claudeUser = claudeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeUser.class)
                    .eq(ClaudeUser::getRelationId, relationId)
                    .last("limit 1"));
            if (claudeUser != null) {
                return claudeUser.getUserToken();
            }
        }
        if (goodsId == Constant.GROK_GOODS_ID) {
            GrokUser grokUser = grokUserMapper.selectOne(Wrappers.lambdaQuery(GrokUser.class)
                    .eq(GrokUser::getRelationId, relationId)
                    .last("limit 1"));
            if (grokUser != null) {
                return grokUser.getUserToken();
            }
        }
        if (goodsId == Constant.LUMA_GOODS_ID) {
            LumaUser lumaUser = lumaUserMapper.selectOne(Wrappers.lambdaQuery(LumaUser.class)
                    .eq(LumaUser::getRelationId, relationId)
                    .last("limit 1"));
            if (lumaUser != null) {
                return lumaUser.getUserToken();
            }
        }
        throw BusinessRuntimeException.getInstance("车票不存在");
    }

    private synchronized ChatgptUser createTrialUser(String clientIP) {
        //固定 sku id
        GoodsDonSku goodsDonSku = skuMapper.selectById(535L);
        //新增体验卡
        ChatgptUser chatgptUser = new ChatgptUser();
        if (goodsDonSku.getIsCar()) {
            chatgptUser.setIsCar(true);
            chatgptUser.setLimitNum(goodsDonSku.getGptLimitNum());
            chatgptUser.setLimitTime(goodsDonSku.getGptLimitTime());
            chatgptUser.setDsLimitNum(goodsDonSku.getDsLimitNum());
            chatgptUser.setDsLimitTime(goodsDonSku.getDsLimitTime());
            chatgptUser.setOtherLimitNum(goodsDonSku.getOtherLimitNum());
            chatgptUser.setOtherLimitTime(goodsDonSku.getOtherLimitTime());
        }
        try {
            DateTime dateTime = DateUtil.offsetMonth(new Date(), 1);
            chatgptUser.setExpireTime(dateTime.toJdkDate());
            chatgptUser.setIsPlus(1);
            chatgptUser.setName("银河体验卡用户");
            chatgptUser.setImg("https://cdn2.yicanggongyi.com/yinhe/icon/index/avatar.png");
            chatgptUser.setUserToken(UUID.randomUUID().toString());
            chatgptUserMapper.insert(chatgptUser);
        } catch (DuplicateKeyException e) {
            log.error("重复插入镜像体验用户ip :{},errmsg:{}",clientIP , StringUtil.getErrorText(e));
        }
        return chatgptUser;
    }
}

