package edu.whut.domain.trade.service.settlement;
import com.alibaba.fastjson.JSON;
import edu.whut.domain.trade.adapter.port.ITradePort;
import edu.whut.domain.trade.adapter.repository.ITradeRepository;
import edu.whut.domain.trade.model.aggregate.GroupBuyTeamSettlementAggregate;
import edu.whut.domain.trade.model.entity.*;
import edu.whut.domain.trade.service.ITradeSettlementOrderService;
import edu.whut.domain.trade.service.settlement.factory.TradeSettlementRuleFilterFactory;
import edu.whut.types.design.framework.link.model2.chain.BusinessLinkedList;
import edu.whut.types.enums.NotifyTaskHTTPEnumVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 拼团交易结算服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TradeSettlementOrderService implements ITradeSettlementOrderService {
    private final ITradeRepository repository;

    private final ITradePort port;

    private final BusinessLinkedList<TradeSettlementRuleCommandEntity, TradeSettlementRuleFilterFactory.DynamicContext, TradeSettlementRuleFilterBackEntity> tradeSettlementRuleFilter;


    /**
     * 第三方支付渠道确认用户“支付成功”之后调用该函数，更新拼团订单状态为 已完成，并同步拼团人数。
     * @param tradePaySuccessEntity 交易支付订单实体对象
     * @return
     */
    @Override
    public TradePaySettlementEntity settlementMarketPayOrder(TradePaySuccessEntity tradePaySuccessEntity) throws Exception {
        log.info("拼团交易-支付订单结算:{} outTradeNo:{}", tradePaySuccessEntity.getUserId(), tradePaySuccessEntity.getOutTradeNo());
        // 1. 结算规则过滤
        TradeSettlementRuleCommandEntity command = new TradeSettlementRuleCommandEntity();
        BeanUtils.copyProperties(tradePaySuccessEntity, command);
        TradeSettlementRuleFilterBackEntity tradeSettlementRuleFilterBackEntity = tradeSettlementRuleFilter.apply(
                command, new TradeSettlementRuleFilterFactory.DynamicContext());
        String teamId=tradeSettlementRuleFilterBackEntity.getTeamId();
        // 2. 查询组团信息
        GroupBuyTeamEntity groupBuyTeamEntity = new GroupBuyTeamEntity();
        BeanUtils.copyProperties(tradeSettlementRuleFilterBackEntity, groupBuyTeamEntity);

        // 3. 构建聚合对象
        GroupBuyTeamSettlementAggregate groupBuyTeamSettlementAggregate = GroupBuyTeamSettlementAggregate.builder()
                .userEntity(UserEntity.builder().userId(tradePaySuccessEntity.getUserId()).build())
                .groupBuyTeamEntity(groupBuyTeamEntity)
                .tradePaySuccessEntity(tradePaySuccessEntity)
                .build();

        // 4. 更新数据库，拼团交易结算
        boolean isNotify =repository.settlementMarketPayOrder(groupBuyTeamSettlementAggregate);

        // 5. isNotify为true-> 付款人数达到target，即拼团成功，执行回调任务
        // 处理失败也会有定时任务补偿，通过这样的方式，可以减轻任务调度，提高时效性
        if (isNotify) {
            Map<String, Integer> notifyResultMap = execSettlementNotifyJob(teamId);
            log.info("回调通知 拼团成功 result:{}", JSON.toJSONString(notifyResultMap));
        }

        // 6. 返回结算信息 - 公司中开发这样的流程时候，会根据外部需要进行值的设置
        return TradePaySettlementEntity.builder()
                .source(tradePaySuccessEntity.getSource())
                .channel(tradePaySuccessEntity.getChannel())
                .userId(tradePaySuccessEntity.getUserId())
                .teamId(teamId)
                .activityId(groupBuyTeamEntity.getActivityId())
                .outTradeNo(tradePaySuccessEntity.getOutTradeNo())
                .build();
    }

    /**
     * 由定时任务触发，定时扫描并执行所有未执行的结算通知任务
     */
    @Override
    public Map<String, Integer> execSettlementNotifyJob() throws Exception {
        log.info("拼团交易-执行结算通知任务");

        // 查询未执行任务
        List<NotifyTaskEntity> notifyTaskEntityList = repository.queryUnExecutedNotifyTaskList();

        return execSettlementNotifyJob(notifyTaskEntityList);
    }

    /**
     * 拼团成功后触发，传入 teamId，执行该 team 下的结算通知回调
     */
    @Override
    public Map<String, Integer> execSettlementNotifyJob(String teamId) throws Exception {
        log.info("拼团交易-执行结算通知回调，指定 teamId:{}", teamId);
        List<NotifyTaskEntity> notifyTaskEntityList = repository.queryUnExecutedNotifyTaskList(teamId);
        return execSettlementNotifyJob(notifyTaskEntityList);
    }

    /**
     *公共逻辑抽取：遍历任务列表，调用外部服务，更新数据库并计数
     * @param notifyTaskEntityList 待处理的通知任务列表
     * @return key——任务总量、successCount、errorCount、retryCount
     */
    private Map<String, Integer> execSettlementNotifyJob(List<NotifyTaskEntity> notifyTaskEntityList) throws Exception {
        int successCount = 0, errorCount = 0, retryCount = 0;
        for (NotifyTaskEntity notifyTask : notifyTaskEntityList) {
            // 回调处理 success 成功，error 失败
            String response = port.groupBuyNotify(notifyTask);

            // 更新状态判断&变更数据库表回调任务状态
            if (NotifyTaskHTTPEnumVO.SUCCESS.getCode().equals(response)) {
                int updateCount = repository.updateNotifyTaskStatusSuccess(notifyTask.getTeamId());
                if (1 == updateCount) {
                    successCount += 1;
                }
            } else if (NotifyTaskHTTPEnumVO.ERROR.getCode().equals(response)) {
                if (notifyTask.getNotifyCount() < 5) {
                    // 失败但可以重试 → 标记为 RETRY，等待下一次收集 “待处理的通知任务列表”
                    if (repository.updateNotifyTaskStatusRetry(notifyTask.getTeamId()) == 1) {
                        retryCount++;
                    }
                } else {
                    // 已达最大重试次数 → 标记为 ERROR（不再重试）
                    if (repository.updateNotifyTaskStatusError(notifyTask.getTeamId()) == 1) {
                        errorCount++;
                    }
                }
            }
        }

        Map<String, Integer> resultMap = new HashMap<>();
        resultMap.put("totalCount", notifyTaskEntityList.size());
        resultMap.put("successCount", successCount);
        resultMap.put("errorCount", errorCount);
        resultMap.put("retryCount", retryCount);

        return resultMap;
    }
}
