package com.red.circle.other.app.command.activity;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.other.app.dto.clientobject.activity.ActivityRewardConfigCO;
import com.red.circle.other.app.dto.clientobject.activity.MyTotalDrawCountCO;
import com.red.circle.other.app.dto.cmd.activity.ActivityRewardConfigCmd;
import com.red.circle.other.app.service.activity.LotteryActivityRestService;
import com.red.circle.other.domain.gateway.props.ActivitySourceGroupGateway;
import com.red.circle.other.infra.database.rds.dao.activity.UserActivityRewardClaimDAO;
import com.red.circle.other.infra.database.rds.entity.activity.UserActivityRewardClaim;
import com.red.circle.other.infra.database.rds.service.activity.UserActivityRechargeService;
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
import com.red.circle.other.inner.model.dto.activity.props.ActivityPropsGroup;
import com.red.circle.other.inner.model.dto.activity.props.ActivityPropsRule;
import com.red.circle.other.inner.model.dto.activity.props.ActivityRewardProps;
import com.red.circle.tool.core.json.JacksonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 查询活动奖励配置执行器
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ActivityRewardConfigBadgeQryExe {

    private final ActivitySourceGroupGateway activitySourceGroupGateway;
    private final UserActivityRewardClaimDAO userActivityRewardClaimDAO;
    private final UserActivityRechargeService userActivityRechargeService;
    private final LotteryActivityRestService lotteryActivityRestService;

    public List<ActivityRewardConfigCO> execute(ActivityRewardConfigCmd cmd) {
        PropsActivityTypeEnum activityType = PropsActivityTypeEnum.valueOf(cmd.getActivityType());
        SysOriginPlatformEnum sysOrigin = SysOriginPlatformEnum.valueOf(cmd.getReqSysOrigin().getOrigin());

        List<ActivityPropsRule> ruleConfigs = activitySourceGroupGateway.listRule(sysOrigin, activityType);
        if (CollectionUtil.isEmpty(ruleConfigs)) {
            return Lists.newArrayList();
        }

        List<Long> ruleIds = ruleConfigs.stream().map(ActivityPropsRule::getId).collect(Collectors.toList());
        Map<Long, UserActivityRewardClaim> claimMap = getUserClaimMap(cmd.getReqUserId(), cmd.getActivityId(), ruleIds);

        MyTotalDrawCountCO drawCount = lotteryActivityRestService.getMyTotalDrawCount(cmd, cmd.getActivityId());


        BigDecimal finalUserTotalAmount = drawCount != null && drawCount.getUsedCount() != null ? new BigDecimal(drawCount.getUsedCount()) : BigDecimal.ZERO;
        return ruleConfigs.stream()
            .map(rule -> buildRewardConfig(rule, cmd.getReqSysOrigin().getOrigin(), claimMap, finalUserTotalAmount))
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
    }

    private Map<Long, UserActivityRewardClaim> getUserClaimMap(Long userId, Long activityId, List<Long> ruleIds) {
        List<UserActivityRewardClaim> claims = userActivityRewardClaimDAO.selectList(
            new LambdaQueryWrapper<UserActivityRewardClaim>()
                .eq(UserActivityRewardClaim::getUserId, userId)
                .eq(UserActivityRewardClaim::getActivityId, activityId)
                .in(UserActivityRewardClaim::getRuleId, ruleIds)
        );

        return claims.stream()
            .collect(Collectors.toMap(UserActivityRewardClaim::getRuleId, claim -> claim, (a, b) -> a));
    }

    private ActivityRewardConfigCO buildRewardConfig(ActivityPropsRule rule, String sysOrigin, 
                                                     Map<Long, UserActivityRewardClaim> claimMap,
                                                     BigDecimal userTotalAmount) {
        ActivityPropsGroup group = activitySourceGroupGateway.getActivityPropsGroup(
            sysOrigin,
            rule.getResourceGroupId()
        );

        if (Objects.isNull(group)) {
            return null;
        }

        ActivityRewardConfigCO config = new ActivityRewardConfigCO()
            .setRuleId(rule.getId())
            .setSysOrigin(rule.getSysOrigin())
            .setActivityType(rule.getActivityType())
            .setResourceGroupId(rule.getResourceGroupId())
            .setJsonData(rule.getJsonData())
            .setSort(rule.getSort())
            .setGroupId(group.getId())
            .setGroupName(group.getName())
            .setShelfStatus(group.getShelfStatus());

        int claimStatus = calculateClaimStatus(rule, claimMap, userTotalAmount);
        config.setClaimStatus(claimStatus);

        if (CollectionUtil.isNotEmpty(group.getActivityRewardProps())) {
            List<ActivityRewardConfigCO.ActivityRewardPropsCO> propsList = group.getActivityRewardProps().stream()
                .map(this::convertToRewardPropsCO)
                .collect(Collectors.toList());
            config.setRewardProps(propsList);
        }

        return config;
    }

    /**
     * 计算领取状态
     * -1: 不可领取（充值金额不足）
     * 0: 可领取（充值金额达标且未领取）
     * 1: 已领取
     */
    private int calculateClaimStatus(ActivityPropsRule rule, 
                                      Map<Long, UserActivityRewardClaim> claimMap,
                                      BigDecimal userTotalAmount) {
        UserActivityRewardClaim claim = claimMap.get(rule.getId());
        if (Objects.nonNull(claim)) {
            return claim.getStatus();
        }

        BigDecimal requiredAmount = parseRequiredAmount(rule.getJsonData());
        if (Objects.isNull(requiredAmount)) {
            return -1;
        }

        if (userTotalAmount.compareTo(requiredAmount) < 0) {
            return -1;
        }

        return 0;
    }

    private BigDecimal parseRequiredAmount(String jsonData) {
        if (StrUtil.isBlank(jsonData)) {
            return null;
        }

        try {
            Map<String, Object> dataMap = JacksonUtils.readValue(jsonData, Map.class);
            Object quantity = dataMap.get("quantity");
            if (Objects.isNull(quantity)) {
                return null;
            }

            if (quantity instanceof Number) {
                return new BigDecimal(quantity.toString());
            }

            if (quantity instanceof String) {
                return new BigDecimal((String) quantity);
            }

            return null;
        } catch (Exception e) {
            log.error("解析jsonData失败: {}", jsonData, e);
            return null;
        }
    }

    private ActivityRewardConfigCO.ActivityRewardPropsCO convertToRewardPropsCO(ActivityRewardProps props) {
        return new ActivityRewardConfigCO.ActivityRewardPropsCO()
            .setId(props.getId())
            .setGroupId(props.getGroupId())
            .setType(props.getType())
            .setDetailType(props.getDetailType())
            .setContent(props.getContent())
            .setSort(props.getSort())
            .setCover(props.getCover())
            .setQuantity(props.getQuantity())
            .setAmount(props.getAmount())
            .setRemark(props.getRemark());
    }
}
