package com.ylx.lottery.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ylx.common.exception.ServiceException;
import com.ylx.lottery.domain.LotteryCountLog;
import com.ylx.lottery.domain.dto.LotteryCountDTO;
import com.ylx.lottery.domain.vo.LotteryActivityVO;
import com.ylx.lottery.domain.vo.LotteryCountResponseVO;
import com.ylx.lottery.domain.vo.LotteryStatVO;
import com.ylx.lottery.service.LotteryCountLogService;
import com.ylx.lottery.service.LotteryCountService;
import com.ylx.usercenter.domain.dto.UnifiedUserCenterDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.TypeReference;

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

@Slf4j
@Service
public class LotteryCountServiceImpl implements LotteryCountService {

    @Value("${remote.local-live.base-url}")
    private String localLiveBaseUrl;

    // 定义接口路径常量
    private static final String LOTTERY_COUNT_ADD_PATH = "/lottery/lotteryUserLotteryCount/batchAdd";
    private static final String LOTTERY_ACTIVITY_LIST_PATH = "/lottery/lotteryActivity/queryActivityList";
    private static final int SCENE_CODE = 2;
    private static final int DEFAULT_TIMEOUT = 5000; // 5秒超时

    @Resource
    private LotteryCountLogService lotteryCountLogService;

    @Override
    public boolean batchAdd(UnifiedUserCenterDTO dto) {

        List<LotteryCountDTO> dtoList = new ArrayList<>();
        // 1. 获取广誉源用户本地未同步抽奖次数
        LambdaQueryWrapper<LotteryCountLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LotteryCountLog::getUserId, dto.getTargetUserId());
        queryWrapper.eq(LotteryCountLog::getStatus, 0);
        queryWrapper.eq(LotteryCountLog::getIsDelete, 0);
        List<LotteryStatVO> resultList = lotteryCountLogService.selectSumByGroup(queryWrapper);

        if (CollUtil.isEmpty(resultList)) {
            log.info("用户[{}]没有待同步的抽奖记录", dto.getTargetUserId());
            return true;
        }

        // 2. 构建请求参数
        for (LotteryStatVO statVO : resultList) {
            LotteryCountDTO countDTO = new LotteryCountDTO();
            countDTO.setAppUserId(dto.getSourceUserId());
            countDTO.setCount(statVO.getTotalNum());
            countDTO.setActivityId(statVO.getLocalActivityTableId());
            dtoList.add(countDTO);
        }

        // 3. 调用接口同步抽奖次数
        try {
            // 1. 构建 URL
            String url = localLiveBaseUrl + LOTTERY_COUNT_ADD_PATH;

            // 2. 转换参数
            String jsonParam = JSON.toJSONString(dtoList);

            // 3. 发送请求
            String result = HttpUtil.post(url, jsonParam, DEFAULT_TIMEOUT);

            // 4. 校验结果
            if (StrUtil.isEmpty(result)) {
                throw new RuntimeException("抽奖次数批量添加接口失败：接口返回空结果");
            }

            // 5. 解析结果
            LotteryCountResponseVO<String> response = JSON.parseObject(
                    result,
                    new TypeReference<LotteryCountResponseVO<String>>() {
                    }
            );

            // 4. 处理业务状态
            if (!response.isSuccess()) {
                log.warn("抽奖次数批量添加接口失败失败: code={}, msg={}", response.getCode(), response.getMessage());
                throw new ServiceException("远程接口返回失败: " + response.getMessage());
            }

            // 5. 更新本地数据库状态
            updateSyncStatus(dto.getTargetUserId());

            return true;

        } catch (Exception e) {
            log.error("抽奖次数批量添加接口发生异常", e);
            throw new ServiceException("抽奖次数批量添加接口异常" + e);
        }

    }

    @Override
    public List<LotteryActivityVO> queryActivityRules() {
        try {
            // 1. 构建请求参数
            String url = localLiveBaseUrl + LOTTERY_ACTIVITY_LIST_PATH;
            Map<String, Object> params = Collections.singletonMap("scene", SCENE_CODE);

            // 2. 发送请求
            String resultJson = HttpUtil.get(url, params, DEFAULT_TIMEOUT);

            // 3. 校验结果
            if (StrUtil.isEmpty(resultJson)) {
                throw new RuntimeException("抽奖规则查询接口失败：接口返回空结果");
            }

            // 4. 解析结果
            LotteryCountResponseVO<List<LotteryActivityVO>> response = JSON.parseObject(
                    resultJson,
                    new TypeReference<LotteryCountResponseVO<List<LotteryActivityVO>>>() {
                    }
            );

            // 5. 处理业务状态
            if (ObjUtil.isNull(response) || !response.isSuccess()) {
                String msg = ObjUtil.isNotNull(response) ? response.getMessage() : "未知错误";
                Integer code = ObjUtil.isNotNull(response) ? response.getCode() : -1;

                log.warn("抽奖规则查询接口业务失败: code={}, msg={}", code, msg);
                throw new ServiceException("远程接口返回失败: " + msg);
            }

            // 6. 获取数据列表
            List<LotteryActivityVO> activityList = response.getResult();

            if (CollUtil.isEmpty(activityList)) {
                log.info("未查询到相关活动数据");
                return Collections.emptyList();
            }

            log.info("成功获取抽奖活动列表，数量: {}", activityList.size());

            return activityList;

        } catch (ServiceException e) {
            // 透传业务异常，不要重复包装
            throw e;
        } catch (Exception e) {
            log.error("抽奖规则查询接口发生系统异常", e);
            // 优化点：只抛出消息，不要直接把整个 Exception 对象 toString() 拼接到字符串里
            throw new ServiceException("抽奖规则查询接口异常: " + e.getMessage());
        }
    }

    private void updateSyncStatus(String userId) {
        LambdaUpdateWrapper<LotteryCountLog> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(LotteryCountLog::getUserId, userId)
                .eq(LotteryCountLog::getStatus, 0) // 只更新未同步的
                .eq(LotteryCountLog::getIsDelete, 0)
                .set(LotteryCountLog::getStatus, 1); // 1-已同步

        boolean updateResult = lotteryCountLogService.update(updateWrapper);
        if (!updateResult) {
            log.warn("用户[{}]抽奖记录状态更新失败", userId);
        } else {
            log.info("用户[{}]抽奖记录状态更新成功", userId);
        }
    }

}
