package com.cyksj.service.grok.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.StringUtil;
import com.cyksj.mapper.*;
import com.cyksj.model.entity.*;
import com.cyksj.model.views.GrokUserView;
import com.cyksj.service.grok.GrokService;
import com.cyksj.service.sys.SysConfigService;
import com.cyksj.service.user.UserBindRelationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * @author chan
 * @date 2025/3/20 18:20
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class GrokServiceImpl implements GrokService {

    private final GoodsDonSkuMapper skuMapper;

    private final GrokUserMapper grokUserMapper;

    private final UserBindRelationService userBindRelationService;

    private final GroupsRelationMapper groupsRelationMapper;

    private final UserMapper userMapper;

    private final GroupsMapper groupsMapper;

    private final SysConfigService sysConfigService;

    @Override
    public GrokUserView getUserInfo(long userId, Long relationId) {
        GrokUser grokUser = checkCarAccount(userId, relationId);
        if (grokUser != null) {

            GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
            GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
            GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());

           GrokUserView view =GrokUserView.builder()
                    .skuName(goodsDonSku.getSubTitle())
                    .expireTime(grokUser.getExpireTime())
                    .limitNum(grokUser.getLimitNum())
                    .limitTime(grokUser.getLimitTime())

                    //.use(Math.min(grokUser.getLimitNum(), getConversationCount(grokUser.getUserToken(),grokUser.getLimitTime())))
                    .build();
            return view;
        } else {
            throw BusinessRuntimeException.getInstance("您还未购买该车票");
        }
    }

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

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

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


    @Override
    public Long getConversationCount(String userToken, Long limitTime) {
        JSONObject conversationCount = getConversationCount(userToken);
        Long count = Optional.ofNullable(conversationCount.getLong("count")).orElse(0l);
        return new BigDecimal(count).divide(BigDecimal.valueOf(4000),0, RoundingMode.HALF_UP).longValue();
    }

    @Override
    public String getCarLoginUrl(String domain, Long userId, Long relationId) {

        GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
        GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
        GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
        if (goodsDonSku != null && goodsDonSku.getIsMirror()) {
            GrokUser grokUser = getGrokUser(userId, relationId, groupsRelation, goodsDonSku);

            String DOMAIN = domain;
            if (StrUtil.isEmpty(DOMAIN)) {
                DOMAIN = "https://grok.bestaistore.com";
                try {
                    SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "mirror_grok_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));
                }
            }
            log.info("domain:{}，用户:{},所在车次:{},座位id:{},在{}获取跳转Grok镜像的登录url", DOMAIN, userId, groupsTrips.getId(), relationId, DateTime.now());
            return DOMAIN + "/signtoken" + "?userToken=" + grokUser.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 GrokUser getGrokUser(Long userId, Long relationId, GroupsRelation groupsRelation, GoodsDonSku goodsDonSku) {
        GrokUser grokUser = grokUserMapper.selectOne(Wrappers.lambdaQuery(GrokUser.class).eq(GrokUser::getRelationId, relationId));
        User user = userMapper.selectById(userId);
        if (grokUser == null) {
            grokUser = createGrokUser(groupsRelation, user, goodsDonSku);
        } else {
            updateGrokUser(groupsRelation, user, grokUser);
        }
        return grokUser;
    }


    /**
     * 创建chatgptUser
     */
    private synchronized GrokUser createGrokUser(GroupsRelation groupsRelation, User user, GoodsDonSku goodsDonSku) {
        GrokUser grokUser = new GrokUser();
        if (goodsDonSku.getIsCar()) {
            grokUser.setLimitNum(goodsDonSku.getGptLimitNum());
            grokUser.setLimitTime(goodsDonSku.getGptLimitTime());
        }
        try {
            grokUser.setExpireTime(groupsRelation.getExpiryTime());
            grokUser.setIsPlus(true);
            grokUser.setName(user.getNickname());
            grokUser.setRelationId(groupsRelation.getId());
            grokUser.setUserToken(UUID.randomUUID().toString());
            grokUserMapper.insert(grokUser);

        } catch (DuplicateKeyException e) {
            log.error("重复插入Grok镜像用户:{}token,errmsg:{}", user.getNickname(), StringUtil.getErrorText(e));
        }
        return grokUser;
    }


    private void updateGrokUser(GroupsRelation groupsRelation, User user, GrokUser grokUser) {
        grokUser.setName(user.getNickname());
        grokUser.setExpireTime(groupsRelation.getExpiryTime());
        grokUserMapper.updateById(grokUser);
    }

    public JSONObject getConversationCount(String userToken) {
        try {
            String res = HttpUtil.get("http://147.79.20.183:9611/grok/getConversationCount?userToken=" + userToken);
            return new JSONObject(res);
        }catch (Exception e){
            return new JSONObject("{\"count\": 0}");
        }
    }

}
