package org.dromara.pay.service;

import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.pay.domain.PayNotifyTask;
import org.dromara.pay.domain.PayOrder;
import org.dromara.pay.mapper.PayNotifyTaskMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 支付通知服务
 *
 * @author pengles
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class PayNotifyService {

    private final PayNotifyTaskMapper baseMapper;

    /**
     * 创建通知任务
     */
    @Transactional(rollbackFor = Exception.class)
    public void createTask(PayOrder order) {
        if (StringUtils.isBlank(order.getNotifyUrl())) {
            return;
        }
        PayNotifyTask task = new PayNotifyTask();
        task.setOrderId(order.getId());
        task.setOrderNo(order.getNo());
        task.setNotifyUrl(order.getNotifyUrl());
        
        Map<String, Object> body = new HashMap<>();
        body.put("orderNo", order.getNo());
        body.put("merchantOrderId", order.getMerchantOrderId());
        body.put("status", order.getStatus());
        body.put("price", order.getPrice());
        body.put("channelUserId", order.getChannelUserId());
        body.put("successTime", order.getSuccessTime());
        body.put("extensionId", order.getExtensionId());
        body.put("channelExtras", order.getChannelExtras());
        
        task.setNotifyBody(JsonUtils.toJsonString(body));
        task.setRetryCount(0);
        task.setMaxRetry(5);
        task.setStatus(0); // 进行中
        task.setNextNotifyTime(new Date()); // 立即执行
        
        baseMapper.insert(task);
        
        // 尝试立即执行一次
        executeTask(task);
    }

    /**
     * 执行通知任务
     */
    public void executeTask(PayNotifyTask task) {
        try {
            log.info("开始执行支付回调通知: taskId={}, url={}", task.getId(), task.getNotifyUrl());
            String result = HttpUtil.post(task.getNotifyUrl(), task.getNotifyBody(), 5000);
            log.info("支付回调通知响应: taskId={}, result={}", task.getId(), result);
            
            // 判断成功：返回 "success" 或 JSON格式 {"code": 200}
            boolean success = false;
            if (StringUtils.isNotBlank(result)) {
                String trimmed = result.trim();
                if ("success".equalsIgnoreCase(trimmed)) {
                    success = true;
                } else {
                    // 尝试解析JSON
                    try {
                        Map<String, Object> jsonResult = JsonUtils.parseMap(trimmed);
                        Object code = jsonResult.get("code");
                        if (code != null) {
                            if (code instanceof Number && ((Number) code).intValue() == 200) {
                                success = true;
                            } else if ("200".equals(String.valueOf(code))) {
                                success = true;
                            }
                        }
                    } catch (Exception e) {
                        // 不是JSON格式，忽略
                    }
                }
            }
            
            if (success) {
                task.setStatus(1); // 成功
                baseMapper.updateById(task);
                return;
            }
        } catch (Exception e) {
            log.error("支付回调通知异常: taskId={}", task.getId(), e);
        }

        // 失败处理
        task.setRetryCount(task.getRetryCount() + 1);
        if (task.getRetryCount() >= task.getMaxRetry()) {
            task.setStatus(2); // 失败
        } else {
            // 计算下次重试时间：指数退避
            // 15s, 30s, 1m, 2m, 5m
            int delaySeconds = 15 * (1 << (task.getRetryCount() - 1));
            task.setNextNotifyTime(new Date(System.currentTimeMillis() + delaySeconds * 1000L));
        }
        baseMapper.updateById(task);
    }

    /**
     * 获取待执行的任务
     */
    public List<PayNotifyTask> getPendingTasks() {
        return baseMapper.selectList(new LambdaQueryWrapper<PayNotifyTask>()
                .eq(PayNotifyTask::getStatus, 0)
                .le(PayNotifyTask::getNextNotifyTime, new Date())
                .last("LIMIT 100"));
    }
}
