package top.continew.admin.business.service.impl;

import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.x.file.storage.core.FileInfo;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import top.continew.admin.business.file.CommonMultipartFile;
import top.continew.admin.business.model.entity.BillingRuleDO;
import top.continew.admin.business.model.entity.ConsumptionHistoryDO;
import top.continew.admin.business.model.entity.PlantformBalanceDO;
import top.continew.admin.business.model.entity.TaskRecordHistoryDO;
import top.continew.admin.business.model.req.*;
import top.continew.admin.system.model.entity.TaskPreDeductDO;
import top.continew.admin.business.model.resp.BillingDeductResp;
import top.continew.admin.business.model.resp.TaskCallbackResp;
import top.continew.admin.business.service.BillingService;
import top.continew.admin.business.service.BillingRuleService;
import top.continew.admin.business.mapper.ConsumptionHistoryMapper;
import top.continew.admin.business.mapper.PlantformBalanceMapper;
import top.continew.admin.business.mapper.TaskRecordHistoryMapper;
import top.continew.admin.system.mapper.TaskPreDeductMapper;
import top.continew.admin.system.model.entity.UserDO;
import top.continew.admin.system.mapper.UserMapper;
import cn.dev33.satoken.stp.StpUtil;
import top.continew.admin.system.service.FileService;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * 计费服务实现类
 *
 * @author jiay
 * @since 2025/08/28 00:00
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class BillingServiceImpl implements BillingService {

    private final TaskRecordHistoryMapper taskRecordHistoryMapper;
    private final ConsumptionHistoryMapper consumptionHistoryMapper;
    private final PlantformBalanceMapper plantformBalanceMapper;
    private final TaskPreDeductMapper taskPreDeductMapper;
    private final UserMapper userMapper;
    private final FileService fileService;
    private final BillingRuleService billingRuleService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BillingDeductResp judgeBalance(BillingJudgeReq req) {
        Long userId = StpUtil.getLoginIdAsLong();
        try {
            // 1. 获取用户信息
            UserDO user = userMapper.selectById(userId);
            if (user == null) {
                return BillingDeductResp.builder().success(false).errorMessage("用户不存在").build();
            }

            // 2. 充点类型不需要预扣减
            if (req.getType() == 0) {
                return BillingDeductResp.builder()
                    .success(true)
                    .remainingBalance(user.getSysBeans())
                    .errorMessage("无需预扣减，充点类型")
                    .build();
            }

            // 3. 根据chargeCode从数据库查询计费规则
            BillingRuleDO billingRule = billingRuleService.getByChargeCode(req.getChargeCode());
            if (billingRule == null) {
                log.error("未找到扣费编码 {} 的计费规则", req.getChargeCode());
                return BillingDeductResp.builder().success(false).errorMessage("未找到对应的计费规则").build();
            }

            Integer quantity = req.getQuantity();
            Long price = billingRule.getPrice() != null ? billingRule.getPrice() : 0L;
            Long subAccountPrice = billingRule.getSubAccountPrice() != null ? billingRule.getSubAccountPrice() : 0L;
            Integer chargeType = billingRule.getChargeType();

            String deductSource = "";
            boolean canDeduct = false;
            Long preDeductAmount = 0L;

            // 4. 优先级1：根据chargeType及用户id从t_plantform_balance取子账户
            if (chargeType != null && subAccountPrice > 0) {
                PlantformBalanceDO subBalance = plantformBalanceMapper
                    .selectOne(new LambdaQueryWrapper<PlantformBalanceDO>().eq(PlantformBalanceDO::getUserId, userId)
                        .eq(PlantformBalanceDO::getChargeType, chargeType));

                if (subBalance != null) {
                    Long availableBalance = subBalance.getBalance() - subBalance.getPreDeductBalance();
                    Long requiredAmount = quantity * subAccountPrice;
                    //大语言模型  Token计费
                    if (chargeType == 0) {
                        requiredAmount = req.getTokens();
                    }
                    if (availableBalance >= requiredAmount) {
                        // 子账户余额足够，使用子账户单价
                        deductSource = "sub_account_" + chargeType;
                        canDeduct = true;
                        preDeductAmount = requiredAmount;

                        // 更新子账号预扣减金额
                        plantformBalanceMapper.update(null, new LambdaUpdateWrapper<PlantformBalanceDO>()
                            .eq(PlantformBalanceDO::getUserId, userId)
                            .eq(PlantformBalanceDO::getChargeType, chargeType)
                            .setSql("pre_deduct_balance = pre_deduct_balance + " + preDeductAmount));

                        log.info("使用子账户扣减, chargeCode: {}, chargeType: {}, requiredAmount: {}, subAccountPrice: {}, preDeductAmount: {}, 剩余子账户: {}", req
                            .getChargeCode(), chargeType, requiredAmount, subAccountPrice, preDeductAmount, availableBalance - preDeductAmount);
                    }
                }
            }

            // 5. 优先级2：如果子账户余额不足，根据用户id及chargeType=11从t_plantform_balance取可学豆子账户
            if (!canDeduct) {
                PlantformBalanceDO kexuedouBalance = plantformBalanceMapper
                    .selectOne(new LambdaQueryWrapper<PlantformBalanceDO>().eq(PlantformBalanceDO::getUserId, userId)
                        .eq(PlantformBalanceDO::getChargeType, 11)); // chargeType=11 是可学豆子账户

                if (kexuedouBalance != null) {
                    Long requiredAmount;
                    if (chargeType != null && chargeType == 0) {
                        // Token类型，需要将token数量转换为点数
                        requiredAmount = calculateTokenToPoints(req.getChargeCode(), req.getTokens());
                        log.info("Token转换为点数, tokens: {}, points: {}", req.getTokens(), requiredAmount);
                    } else {
                        // 非token类型，直接使用 quantity * price
                        requiredAmount = quantity * price;
                    }
                    Long availableBalance = kexuedouBalance.getBalance() - kexuedouBalance.getPreDeductBalance();

                    if (availableBalance >= requiredAmount) {
                        deductSource = "kexuedou_account";
                        canDeduct = true;
                        preDeductAmount = requiredAmount;

                        // 更新可学豆子账户预扣减金额
                        plantformBalanceMapper.update(null, new LambdaUpdateWrapper<PlantformBalanceDO>()
                            .eq(PlantformBalanceDO::getUserId, userId)
                            .eq(PlantformBalanceDO::getChargeType, 11)
                            .setSql("pre_deduct_balance = pre_deduct_balance + " + preDeductAmount));

                    }
                }
            }

            if (!canDeduct) {
                Long requiredAmount;
                if (chargeType != null && chargeType == 0) {
                    // Token类型，需要将token数量转换为点数
                    requiredAmount = calculateTokenToPoints(req.getChargeCode(), req.getTokens());
                    log.info("Token转换为点数(主账户), tokens: {}, points: {}", req.getTokens(), requiredAmount);
                } else {
                    // 非token类型，直接使用 quantity * price
                    requiredAmount = quantity * price;
                }
                Long actualBalance = (user.getSysBeans() != null ? user.getSysBeans().longValue() : 0L);
                Long preDeductedBalance = (user.getPreDeductBeans() != null
                    ? user.getPreDeductBeans().longValue()
                    : 0L);
                Long availableBalance = actualBalance - preDeductedBalance;

                if (availableBalance >= requiredAmount) {
                    deductSource = "main_account";
                    canDeduct = true;
                    preDeductAmount = requiredAmount;

                    // 更新主账户预扣减金额
                    userMapper.addPreDeductBeansById(userId, preDeductAmount);

                } else {
                    log.warn("主账户余额不足, chargeCode: {}, 需要: {}分, 可用: {}分", req
                        .getChargeCode(), requiredAmount, availableBalance);
                }
            }

            if (!canDeduct) {
                return BillingDeductResp.builder().success(false).errorMessage("可用余额不足，请充值").build();
            }

            // 7. 创建或更新预扣减记录
            TaskPreDeductDO existingPreDeduct = taskPreDeductMapper.selectOne(new LambdaQueryWrapper<TaskPreDeductDO>()
                .eq(TaskPreDeductDO::getUserId, userId)
                .eq(TaskPreDeductDO::getChargeType, req.getChargeType()));

            if (existingPreDeduct != null) {
                // 存在记录，更新
                existingPreDeduct.setPreDeductAmount(preDeductAmount + existingPreDeduct.getPreDeductAmount());
                existingPreDeduct.setDeductSource(deductSource);
                existingPreDeduct.setStatus(0); // 0: 进行中

                taskPreDeductMapper.updateById(existingPreDeduct);
            } else {
                // 不存在记录，新增
                TaskPreDeductDO preDeductRecord = new TaskPreDeductDO();
                preDeductRecord.setUserId(userId);
                preDeductRecord.setChargeType(req.getChargeType());
                preDeductRecord.setPreDeductAmount(preDeductAmount);
                preDeductRecord.setDeductSource(deductSource);
                preDeductRecord.setStatus(0); // 0: 进行中

                taskPreDeductMapper.insert(preDeductRecord);
            }

            // 8. 返回校验成功结果
            return BillingDeductResp.builder()
                .success(true)
                .remainingBalance(user.getSysBeans())
                .errorMessage("余额校验通过并已预扣减，来源: " + deductSource)
                .build();

        } catch (Exception e) {
            log.error("余额校验失败, userId: {}, req: {}", userId, req, e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskCallbackResp taskCallback(TaskCallbackReq req) {
        Long userId = StpUtil.getLoginIdAsLong();
        try {
            // 1. 查找预扣减记录
            TaskPreDeductDO preDeductRecord = taskPreDeductMapper.selectOne(new LambdaQueryWrapper<TaskPreDeductDO>()
                .eq(TaskPreDeductDO::getUserId, userId)
                .eq(TaskPreDeductDO::getChargeType, req.getChargeType())
            // .eq(TaskPreDeductDO::getStatus, 0) // 进行中的任务
            );

            if (preDeductRecord == null) {
                return TaskCallbackResp.builder().success(false).message("未找到对应的预扣减记录").build();
            }

            // 2. 根据任务状态处理
            if (req.getStatus() == 1) { // 任务成功
                return handleSuccessCallback(req, preDeductRecord, userId);
            } else if (req.getStatus() == 0) {
                return TaskCallbackResp.builder().success(false).message("任务进行中").build();
            } else { // 任务失败或取消
                return handleFailureCallback(req, preDeductRecord, userId);
            }

        } catch (Exception e) {
            log.error("任务回调异常, taskId: {}, req: {}", req.getTaskId(), req, e);
            return TaskCallbackResp.builder().success(false).message("任务回调异常: " + e.getMessage()).build();
        }
    }

    /**
     * 处理任务成功的回调
     */
    private TaskCallbackResp handleSuccessCallback(TaskCallbackReq req, TaskPreDeductDO preDeductRecord, Long userId) {
        // 1. 根据chargeCode查询计费规则，计算实际消费点数
        Long actualConsumptionPoints;
        Integer actualQuantity = req.getQuantity() != null ? req.getQuantity() : 1;

        if (req.getChargeCode() == null) {
            log.error("扣费编码不能为空");
            return TaskCallbackResp.builder().success(false).message("扣费编码不能为空").build();
        }

        // 查询计费规则
        BillingRuleDO billingRule = billingRuleService.getByChargeCode(req.getChargeCode());
        if (billingRule == null) {
            log.error("未找到扣费编码 {} 的计费规则", req.getChargeCode());
            return TaskCallbackResp.builder().success(false).message("未找到对应的计费规则").build();
        }

        String deductSource = preDeductRecord.getDeductSource();
        Integer chargeType = billingRule.getChargeType();

        // 特殊处理：chargeType=0 表示大语言模型，使用token计费
        if (chargeType != null && chargeType == 0) {
            // Token计费类型
            if (deductSource != null && deductSource.startsWith("sub_account_")) {
                actualConsumptionPoints = req.getTokens();
                // 从token子账户扣减，直接扣除token数量
                log.info("Token子账户扣费, chargeCode: {}, actualTokens: {}", req.getChargeCode(), actualConsumptionPoints);
            } else {
                // 从可学豆或主账户扣减，需要根据扣费编码计算点数
                actualConsumptionPoints = calculateTokenToPoints(req.getChargeCode(), req.getTokens());
            }
        } else {
            // 非token类型，按数量计费
            if (deductSource != null && deductSource.startsWith("sub_account_")) {
                // 子账户扣减，使用子账户单价
                Long subAccountPrice = billingRule.getSubAccountPrice() != null ? billingRule.getSubAccountPrice() : 0L;
                actualConsumptionPoints = actualQuantity * subAccountPrice;
            } else {
                // 可学豆子账户或主账户扣减，使用主账户单价
                Long price = billingRule.getPrice() != null ? billingRule.getPrice() : 0L;
                actualConsumptionPoints = actualQuantity * price;
            }
        }

        // 2. 创建任务记录
        TaskRecordHistoryDO taskRecord = new TaskRecordHistoryDO();
        taskRecord.setUserId(userId);
        taskRecord.setPlatformId(req.getPlatformId());
        taskRecord.setTaskId(req.getTaskId());
        taskRecord.setTitle(req.getTitle());
        taskRecord.setTaskType(req.getTaskType());
        taskRecord.setChargeType(req.getChargeType());
        taskRecord.setModelName(req.getModelName());
        taskRecord.setConsumptionPoints(actualConsumptionPoints);
        taskRecord.setPlatformCode(req.getPlatformCode());
        taskRecord.setAccountType(deductSource);

        // 设置文件路径或文字内容
        if (req.getTaskType() == 0 || !StringUtils.hasText(req.getFileUrl())) { // token类型或文字类型
            taskRecord.setResult(req.getResult());
            taskRecord.setTokens(req.getTokens());
            taskRecordHistoryMapper.insert(taskRecord);
        } else { // 音视频图片类型(2,3,4,5)
            addTaskRecordHistory(taskRecord, req);
        }

        // 3. 创建消费记录
        ConsumptionHistoryDO consumption = new ConsumptionHistoryDO();
        consumption.setUserId(userId);
        consumption.setPlatformId(req.getPlatformId());
        consumption.setTaskType(req.getTaskType());
        consumption.setChargePoints(actualConsumptionPoints);

        // 4. 根据扣减来源进行实际扣费和清零预扣减
        if (deductSource != null && deductSource.startsWith("sub_account_")) {
            // 子账户扣费（chargeType特定的子账户，如sub_account_1, sub_account_3等）
            PlantformBalanceDO balance = plantformBalanceMapper.selectOne(new LambdaQueryWrapper<PlantformBalanceDO>()
                .eq(PlantformBalanceDO::getUserId, userId)
                .eq(PlantformBalanceDO::getChargeType, chargeType));

            consumption.setRemainingPoints(balance.getBalance() - actualConsumptionPoints);
            consumption.setType(req.getType()); // 消费类型
            consumption.setAccountType(1); // 1子账号

            // 扣减实际金额并清零预扣减
            plantformBalanceMapper.update(null, new LambdaUpdateWrapper<PlantformBalanceDO>()
                .eq(PlantformBalanceDO::getUserId, userId)
                .eq(PlantformBalanceDO::getChargeType, chargeType)
                .setSql("balance = balance - " + actualConsumptionPoints + ", pre_deduct_balance = pre_deduct_balance - " + preDeductRecord
                    .getPreDeductAmount()));

        } else if ("kexuedou_account".equals(deductSource)) {
            // 可学豆子账户扣费（chargeType=11的子账户）
            PlantformBalanceDO balance = plantformBalanceMapper.selectOne(new LambdaQueryWrapper<PlantformBalanceDO>()
                .eq(PlantformBalanceDO::getUserId, userId)
                .eq(PlantformBalanceDO::getChargeType, 11));

            consumption.setRemainingPoints(balance.getBalance() - actualConsumptionPoints);
            consumption.setType(req.getType()); // 消费类型
            consumption.setAccountType(1); // 1子账号

            // 扣减实际金额并清零预扣减
            plantformBalanceMapper.update(null, new LambdaUpdateWrapper<PlantformBalanceDO>()
                .eq(PlantformBalanceDO::getUserId, userId)
                .eq(PlantformBalanceDO::getChargeType, 11)
                .setSql("balance = balance - " + actualConsumptionPoints + ", pre_deduct_balance = pre_deduct_balance - " + preDeductRecord
                    .getPreDeductAmount()));

            log.info("可学豆子账户扣费完成, actualConsumption: {}", actualConsumptionPoints);
        } else if ("main_account".equals(deductSource)) {
            // 主账户sys_beans扣费
            UserDO user = userMapper.selectById(userId);
            consumption.setRemainingPoints(user.getSysBeans().longValue() - actualConsumptionPoints);
            consumption.setType(req.getType()); // 消费类型
            consumption.setAccountType(0); // 0主账号

            // 原子操作：扣减实际金额并清零预扣减   单位为分
            int updateResult = userMapper.deductActualAndClearPreDeduct(userId, preDeductRecord
                .getPreDeductAmount(), actualConsumptionPoints);
            if (updateResult == 0) {
                throw new RuntimeException("扣减用户余额失败");
            }

            log.info("主账户扣费完成, actualConsumption: {}", actualConsumptionPoints);
        } else {
            log.error("未知的扣减来源: {}", deductSource);
            throw new RuntimeException("未知的扣减来源: " + deductSource);
        }

        consumptionHistoryMapper.insert(consumption);

        // 5. 更新预扣减记录状态
        preDeductRecord.setStatus(1); // 1: 已完成
        taskPreDeductMapper.updateById(preDeductRecord);

        log.info("任务成功回调完成, taskId: {}, userId: {}, platformCode: {}, preDeduct: {}, actual: {}", req
            .getTaskId(), userId, req.getPlatformCode(), preDeductRecord.getPreDeductAmount(), actualConsumptionPoints);

        return TaskCallbackResp.builder().success(true).message("任务成功，扣费完成").taskRecordId(taskRecord.getId()).build();
    }

    /**
     * 从字符串中提取时间
     *
     * @param dateTimeString 时间字符串
     * @return LocalDateTime
     */
    private static LocalDateTime extractDateTime(String dateTimeString) {
        try {
            if (dateTimeString == null || dateTimeString.isEmpty()) {
                return null;
            }
            return LocalDateTime.parse(dateTimeString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 将token数量转换为点数（用于从可学豆或主账户扣减）
     *
     * @param chargeCode 扣费编码
     * @param tokens     token数量
     * @return 消费点数（分）
     */
    private Long calculateTokenToPoints(String chargeCode, Long tokens) {
        if (tokens == null || tokens <= 0) {
            return 0L;
        }

        Long points;
        Long minPoints;

        // 根据扣费编码确定费率和最低扣费
        switch (chargeCode) {
            case "C5000":
                // 100万token=200分，单次最低2分
                points = (tokens * 200 + 999999) / 1000000; // 向上取整
                minPoints = 2L;
                break;
            case "C5001":
                // 100万token=150分，单次最低2分
                points = (tokens * 150 + 999999) / 1000000; // 向上取整
                minPoints = 2L;
                break;
            case "C5002":
                // 100万token=400分，单次最低5分
                points = (tokens * 400 + 999999) / 1000000; // 向上取整
                minPoints = 5L;
                break;
            case "C5003":
                // 100万token=200分，单次最低6分
                points = (tokens * 200 + 999999) / 1000000; // 向上取整
                minPoints = 6L;
                break;
            case "C7000":
                // 100万token=200分，单次最低3分
                points = (tokens * 200 + 999999) / 1000000; // 向上取整
                minPoints = 3L;
                break;
            default:
                log.warn("未配置扣费编码 {} 的token转换规则，使用默认规则", chargeCode);
                // 默认：100万token=200分，单次最低2分
                points = (tokens * 200 + 999999) / 1000000;
                minPoints = 2L;
                break;
        }

        // 确保不低于最低扣费
        return Math.max(points, minPoints);
    }

    /**
     * 处理任务失败的回调
     */
    private TaskCallbackResp handleFailureCallback(TaskCallbackReq req, TaskPreDeductDO preDeductRecord, Long userId) {
        // 1. 恢复预扣减的金额
        String deductSource = preDeductRecord.getDeductSource();
        if (deductSource != null && deductSource.startsWith("sub_account_")) {
            // 恢复子账户预扣减金额（chargeType特定的子账户）
            // 从deductSource中提取chargeType
            Integer chargeType = Integer.parseInt(deductSource.substring("sub_account_".length()));

            plantformBalanceMapper.update(null, new LambdaUpdateWrapper<PlantformBalanceDO>()
                .eq(PlantformBalanceDO::getUserId, userId)
                .eq(PlantformBalanceDO::getChargeType, chargeType)
                .setSql("pre_deduct_balance = pre_deduct_balance - " + preDeductRecord.getPreDeductAmount()));

            log.info("子账户预扣减恢复完成, chargeType: {}, amount: {}", chargeType, preDeductRecord.getPreDeductAmount());
        } else if ("kexuedou_account".equals(deductSource)) {
            // 恢复可学豆子账户预扣减金额（chargeType=11）
            plantformBalanceMapper.update(null, new LambdaUpdateWrapper<PlantformBalanceDO>()
                .eq(PlantformBalanceDO::getUserId, userId)
                .eq(PlantformBalanceDO::getChargeType, 11)
                .setSql("pre_deduct_balance = pre_deduct_balance - " + preDeductRecord.getPreDeductAmount()));

            log.info("可学豆子账户预扣减恢复完成, amount: {}", preDeductRecord.getPreDeductAmount());
        } else if ("main_account".equals(deductSource)) {
            // 恢复主账户预扣减金额
            userMapper.clearPreDeductBeansById(userId, preDeductRecord.getPreDeductAmount());

            log.info("主账户预扣减恢复完成, amount: {}", preDeductRecord.getPreDeductAmount());
        } else {
            log.error("未知的扣减来源: {}", deductSource);
            throw new RuntimeException("未知的扣减来源: " + deductSource);
        }

        // 2. 更新预扣减记录状态
        preDeductRecord.setStatus(req.getStatus() == 2 ? 2 : 3); // 2: 已失败, 3: 已取消
        taskPreDeductMapper.updateById(preDeductRecord);

        return TaskCallbackResp.builder().success(true).message("任务失败，预扣减金额已恢复").build();
    }

    private void addTaskRecordHistory(TaskRecordHistoryDO taskRecord, TaskCallbackReq req) {
        String fileStr = req.getFileUrl();
        // 检查fileUrl是否为空，为空则直接插入记录
        if (StrUtil.isEmpty(fileStr)) {
            taskRecordHistoryMapper.insert(taskRecord);
            return;
        }
        //先下载文件
        List<String> fileUrls = Arrays.asList(fileStr.split(","));
        if (!fileUrls.isEmpty()) {
            fileUrls.forEach(fileUrl -> {
                if (StrUtil.isEmpty(fileUrl)) {
                    throw new RuntimeException("文件url地址为空");
                }
                FileInfo upload;
                try {
                    // 1. 构造URL格式
                    URL url = new URL(fileUrl);
                    // 2. 打开HTTP连接并配置参数
                    HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                    connection.setRequestMethod("GET");
                    // 5秒连接超时
                    connection.setConnectTimeout(5000);
                    // 10秒读取超时
                    connection.setReadTimeout(10000);
                    // 设置User-Agent
                    connection.setRequestProperty("User-Agent", "Mozilla/5.0");
                    // 3. 检查HTTP响应状态码
                    int responseCode = connection.getResponseCode();
                    if (responseCode != HttpURLConnection.HTTP_OK) {
                        throw new IOException("HTTP请求失败，状态码: " + responseCode);
                    }
                    // 4. 获取输入流（注意：调用者需负责关闭此流）
                    InputStream inputStream = connection.getInputStream();
                    String fileName = extractFileName(fileUrl);
                    // 过滤非法字符
                    String safeFileName = sanitizeFileName(fileName);
                    String uniqueName = UUID.randomUUID() + "_" + safeFileName;
                    MultipartFile multipartFile = new CommonMultipartFile(uniqueName, safeFileName, MediaType.MULTIPART_FORM_DATA_VALUE, inputStream);
                    upload = fileService.upload(multipartFile);

                } catch (Exception e) {
                    log.error(e.getMessage());
                    throw new RuntimeException("文件下载失败");
                }
                //插入记录到数据库
                taskRecord.setFileUrl(upload.getUrl());
                taskRecordHistoryMapper.insert(taskRecord);
            });
        }
    }

    private static String extractFileName(String fileUrl) {
        try {
            URI uri = URI.create(fileUrl);
            String path = uri.getPath();
            if (path == null || path.isEmpty()) {
                return "unknown_" + System.currentTimeMillis();
            }
            // 提取最后一个斜杠后的内容
            String rawName = path.substring(path.lastIndexOf('/') + 1);

            // 去除URL参数（如?foo=bar）
            return rawName.contains("?") ? rawName.split("\\?")[0] : rawName;
        } catch (Exception e) {
            return "unknown_" + System.currentTimeMillis();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BillingDeductResp judgeBalanceWithAmount(BillingJudgeWithAmountReq req) {
        Long userId = StpUtil.getLoginIdAsLong();
        try {
            // 1. 获取用户信息
            UserDO user = userMapper.selectById(userId);
            if (user == null) {
                return BillingDeductResp.builder().success(false).errorMessage("用户不存在").build();
            }

            String deductSource = "";
            boolean canDeduct = false;
            Integer chargeType = req.getChargeType();
            Long preDeductAmount = 0L;
            // 2. 充点类型不需要预扣减
            if (req.getType() == 0) {
                return BillingDeductResp.builder()
                    .success(true)
                    .remainingBalance(user.getSysBeans())
                    .errorMessage("无需预扣减，充点类型")
                    .build();
            } else if (req.getType() == 1) {
                // 3. 使用第三方平台传入的预扣减金额
                preDeductAmount = req.getQuantity().longValue();
                // 4. 优先级1：检查子账户余额
                PlantformBalanceDO subBalance = plantformBalanceMapper
                    .selectOne(new LambdaQueryWrapper<PlantformBalanceDO>().eq(PlantformBalanceDO::getUserId, userId)
                        .eq(PlantformBalanceDO::getChargeType, chargeType));

                if (subBalance != null) {
                    Long availableBalance = subBalance.getBalance() - subBalance.getPreDeductBalance();

                    if (availableBalance >= preDeductAmount) {
                        // 子账户余额足够
                        deductSource = "sub_account_" + chargeType;
                        canDeduct = true;

                        // 更新子账号预扣减金额
                        plantformBalanceMapper.update(null, new LambdaUpdateWrapper<PlantformBalanceDO>()
                            .eq(PlantformBalanceDO::getUserId, userId)
                            .eq(PlantformBalanceDO::getChargeType, chargeType)
                            .setSql("pre_deduct_balance = pre_deduct_balance + " + preDeductAmount));
                    }
                }
            } else if (req.getType() == 2) {
                preDeductAmount = req.getPreDeductAmount();
                // 5. 优先级2：如果子账户余额不足，检查可学豆子账户
                if (!canDeduct) {
                    PlantformBalanceDO kexuedouBalance = plantformBalanceMapper
                        .selectOne(new LambdaQueryWrapper<PlantformBalanceDO>()
                            .eq(PlantformBalanceDO::getUserId, userId)
                            .eq(PlantformBalanceDO::getChargeType, 11)); // chargeType=11 是可学豆子账户

                    if (kexuedouBalance != null) {
                        Long availableBalance = kexuedouBalance.getBalance() - kexuedouBalance.getPreDeductBalance();

                        if (availableBalance >= preDeductAmount) {
                            deductSource = "kexuedou_account";
                            canDeduct = true;

                            // 更新可学豆子账户预扣减金额
                            plantformBalanceMapper.update(null, new LambdaUpdateWrapper<PlantformBalanceDO>()
                                .eq(PlantformBalanceDO::getUserId, userId)
                                .eq(PlantformBalanceDO::getChargeType, 11)
                                .setSql("pre_deduct_balance = pre_deduct_balance + " + preDeductAmount));
                        }
                    }
                }
                if (!canDeduct) {
                    Long actualBalance = (user.getSysBeans() != null ? user.getSysBeans().longValue() : 0L);
                    Long preDeductedBalance = (user.getPreDeductBeans() != null
                        ? user.getPreDeductBeans().longValue()
                        : 0L);
                    Long availableBalance = actualBalance - preDeductedBalance;

                    if (availableBalance >= preDeductAmount) {
                        deductSource = "main_account";
                        canDeduct = true;

                        // 更新主账户预扣减金额
                        userMapper.addPreDeductBeansById(userId, preDeductAmount);

                        log.info("使用主账户扣减(第三方金额), preDeductAmount: {}分, 剩余主账户: {}分", preDeductAmount, availableBalance - preDeductAmount);
                    } else {
                        log.warn("主账户余额不足(第三方金额), 需要: {}分, 可用: {}分", preDeductAmount, availableBalance);
                    }
                }
            }

            if (!canDeduct) {
                return BillingDeductResp.builder().success(false).errorMessage("可用余额不足，请充值").build();
            }

            // 7. 创建或更新预扣减记录
            TaskPreDeductDO existingPreDeduct = taskPreDeductMapper.selectOne(new LambdaQueryWrapper<TaskPreDeductDO>()
                .eq(TaskPreDeductDO::getUserId, userId)
                .eq(TaskPreDeductDO::getChargeType, chargeType));

            if (existingPreDeduct != null) {
                // 存在记录，更新
                existingPreDeduct.setPreDeductAmount(preDeductAmount + existingPreDeduct.getPreDeductAmount());
                existingPreDeduct.setDeductSource(deductSource);
                existingPreDeduct.setStatus(0); // 0: 进行中

                taskPreDeductMapper.updateById(existingPreDeduct);
                log.info("更新预扣减记录成功(第三方金额), userId: {}, amount: {}, source: {}", userId, preDeductAmount, deductSource);
            } else {
                // 不存在记录，新增
                TaskPreDeductDO preDeductRecord = new TaskPreDeductDO();
                preDeductRecord.setUserId(userId);
                preDeductRecord.setChargeType(chargeType);
                preDeductRecord.setPreDeductAmount(preDeductAmount);
                preDeductRecord.setDeductSource(deductSource);
                preDeductRecord.setStatus(0); // 0: 进行中

                taskPreDeductMapper.insert(preDeductRecord);
                log.info("创建预扣减记录成功(第三方金额), userId: {}, amount: {}, source: {}", userId, preDeductAmount, deductSource);
            }

            // 8. 返回校验成功结果
            return BillingDeductResp.builder()
                .success(true)
                .remainingBalance(user.getSysBeans())
                .errorMessage("余额校验通过并已预扣减(第三方金额)，来源: " + deductSource)
                .build();

        } catch (Exception e) {
            log.error("余额校验失败(第三方金额), userId: {}, req: {}", userId, req, e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskCallbackResp taskCallbackWithAmount(TaskCallbackWithAmountReq req) {
        Long userId = StpUtil.getLoginIdAsLong();
        try {
            // 1. 查找预扣减记录
            TaskPreDeductDO preDeductRecord = taskPreDeductMapper.selectOne(new LambdaQueryWrapper<TaskPreDeductDO>()
                .eq(TaskPreDeductDO::getUserId, userId)
                .eq(TaskPreDeductDO::getChargeType, req.getChargeType())
            //.eq(TaskPreDeductDO::getStatus, 0) // 进行中的任务
            );

            if (preDeductRecord == null) {
                return TaskCallbackResp.builder().success(false).message("未找到对应的预扣减记录").build();
            }

            // 2. 根据任务状态处理
            if (req.getStatus() == 1) {
                // 任务成功，使用第三方传入的实际消费金额进行扣费
                return handleSuccessCallbackWithAmount(req, preDeductRecord, userId);
            } else {
                // 任务失败或取消，恢复预扣减（与原逻辑相同）
                return handleFailureCallback(req, preDeductRecord, userId);
            }

        } catch (Exception e) {
            log.error("任务回调失败(第三方金额), userId: {}, taskId: {}", userId, req.getTaskId(), e);
            throw e;
        }
    }

    @Override
    public Page<TaskRecordHistoryDO> queryTaskListByRootId(TaskQueryReq req) {
        try {
            // 根据根任务ID查询任务列表
            LambdaQueryWrapper<TaskRecordHistoryDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(TaskRecordHistoryDO::getTaskRootId, req.getTaskRootId());
            queryWrapper.orderByDesc(TaskRecordHistoryDO::getCreateTime);

            // 分页查询
            Page<TaskRecordHistoryDO> page = new Page<>(req.getPage(), req.getSize());
            Page<TaskRecordHistoryDO> resultPage = taskRecordHistoryMapper.selectPage(page, queryWrapper);

            return resultPage;
        } catch (Exception e) {
            log.error("查询任务列表失败, taskRootId: {}", req.getTaskRootId(), e);
            return null;
        }
    }

    /**
     * 处理任务成功的回调（使用第三方传入的实际消费金额）
     */
    private TaskCallbackResp handleSuccessCallbackWithAmount(TaskCallbackWithAmountReq req,
                                                             TaskPreDeductDO preDeductRecord,
                                                             Long userId) {
        String deductSource = preDeductRecord.getDeductSource();
        //        Integer chargeType = req.getChargeType();

        // 使用第三方平台传入的实际消费金额
        Long actualConsumptionPoints = req.getActualAmount();
        if (req.getType() == 1) {
            actualConsumptionPoints = req.getQuantity().longValue();
        }

        log.info("使用第三方传入的实际消费金额, actualAmount: {}", actualConsumptionPoints);

        // 2. 创建任务记录
        //        TaskRecordHistoryDO taskRecord = new TaskRecordHistoryDO();
        //        taskRecord.setUserId(userId);
        //        taskRecord.setPlatformId(req.getPlatformId());
        //        taskRecord.setTaskId(req.getTaskId());
        //        taskRecord.setTitle(req.getTitle());
        //        taskRecord.setTaskType(req.getTaskType());
        //        taskRecord.setChargeType(req.getChargeType());
        //        taskRecord.setModelName(req.getModelName());
        //        taskRecord.setConsumptionPoints(actualConsumptionPoints);
        //        taskRecord.setPlatformCode(req.getPlatformCode());
        //        taskRecord.setAccountType(deductSource);

        //换哒新表补充字段
        //        taskRecord.setParentCreateTime(extractDateTime(req.getParentCreateTime()));
        //        taskRecord.setTaskRootId(req.getTaskRootId());
        //        if (req.getParentTaskId() != null) {
        //            taskRecord.setParentTaskId(req.getParentTaskId());
        //        }
        //
        //        // 设置文件路径或文字内容
        //        if (req.getTaskType() == 0 || !StringUtils.hasText(req.getFileUrl())) { // token类型或文字类型
        //            taskRecord.setResult(req.getResult());
        //            taskRecord.setTokens(req.getTokens());
        //            taskRecordHistoryMapper.insert(taskRecord);
        //        } else { // 音视频图片类型(2,3,4,5)
        //            addTaskRecordHistory(taskRecord, req);
        //        }

        // 3. 创建消费记录
        //        ConsumptionHistoryDO consumption = new ConsumptionHistoryDO();
        //        consumption.setUserId(userId);
        //        consumption.setPlatformId(req.getPlatformId());
        //        consumption.setTaskType(req.getTaskType());
        //        consumption.setChargePoints(actualConsumptionPoints);

        // 4. 根据扣减来源进行实际扣费和清零预扣减
        if (deductSource != null && deductSource.startsWith("sub_account_")) {
            // 子账户扣费（chargeType特定的子账户）
            Integer extractedChargeType = Integer.parseInt(deductSource.substring("sub_account_".length()));

            //            PlantformBalanceDO balance = plantformBalanceMapper.selectOne(new LambdaQueryWrapper<PlantformBalanceDO>()
            //                .eq(PlantformBalanceDO::getUserId, userId)
            //                .eq(PlantformBalanceDO::getChargeType, extractedChargeType));

            //            consumption.setRemainingPoints(balance.getBalance() - actualConsumptionPoints);
            //            consumption.setType(req.getType()); // 消费类型
            //            consumption.setAccountType(1); // 1子账号

            // 扣减实际金额并清零预扣减
            plantformBalanceMapper.update(null, new LambdaUpdateWrapper<PlantformBalanceDO>()
                .eq(PlantformBalanceDO::getUserId, userId)
                .eq(PlantformBalanceDO::getChargeType, extractedChargeType)
                .setSql("balance = balance - " + actualConsumptionPoints + ", pre_deduct_balance = pre_deduct_balance - " + preDeductRecord
                    .getPreDeductAmount()));

            log.info("子账户扣费完成(第三方金额), chargeType: {}, actualConsumption: {}", extractedChargeType, actualConsumptionPoints);
        } else if ("kexuedou_account".equals(deductSource)) {
            // 可学豆子账户扣费（chargeType=11的子账户）
            //            PlantformBalanceDO balance = plantformBalanceMapper.selectOne(new LambdaQueryWrapper<PlantformBalanceDO>()
            //                .eq(PlantformBalanceDO::getUserId, userId)
            //                .eq(PlantformBalanceDO::getChargeType, 11));

            //            consumption.setRemainingPoints(balance.getBalance() - actualConsumptionPoints);
            //            consumption.setType(req.getType()); // 消费类型
            //            consumption.setAccountType(1); // 1子账号

            // 扣减实际金额并清零预扣减
            plantformBalanceMapper.update(null, new LambdaUpdateWrapper<PlantformBalanceDO>()
                .eq(PlantformBalanceDO::getUserId, userId)
                .eq(PlantformBalanceDO::getChargeType, 11)
                .setSql("balance = balance - " + actualConsumptionPoints + ", pre_deduct_balance = pre_deduct_balance - " + preDeductRecord
                    .getPreDeductAmount()));

            log.info("可学豆子账户扣费完成(第三方金额), actualConsumption: {}", actualConsumptionPoints);
        } else if ("main_account".equals(deductSource)) {
            // 主账户sys_beans扣费
            //            UserDO user = userMapper.selectById(userId);
            //            consumption.setRemainingPoints(user.getSysBeans().longValue() - actualConsumptionPoints);
            //            consumption.setType(req.getType()); // 消费类型
            //            consumption.setAccountType(0); // 0主账号

            // 原子操作：扣减实际金额并清零预扣减   单位为分
            int updateResult = userMapper.deductActualAndClearPreDeduct(userId, preDeductRecord
                .getPreDeductAmount(), actualConsumptionPoints);
            if (updateResult == 0) {
                throw new RuntimeException("扣减用户余额失败");
            }

            log.info("主账户扣费完成(第三方金额), actualConsumption: {}", actualConsumptionPoints);
        } else {
            log.error("未知的扣减来源: {}", deductSource);
            throw new RuntimeException("未知的扣减来源: " + deductSource);
        }

        //        consumptionHistoryMapper.insert(consumption);

        // 5. 更新预扣减记录状态
        preDeductRecord.setStatus(1); // 1: 已完成
        taskPreDeductMapper.updateById(preDeductRecord);

        log.info("任务成功回调完成(第三方金额), taskId: {}, userId: {}, platformCode: {}, preDeduct: {}, actual: {}", req
            .getTaskId(), userId, req.getPlatformCode(), preDeductRecord.getPreDeductAmount(), actualConsumptionPoints);

        return TaskCallbackResp.builder().success(true).message("任务成功，扣费完成(第三方金额)").build();
    }

    // 过滤非法文件名字符（Windows/Linux兼容）
    private static String sanitizeFileName(String fileName) {
        // 替换非法字符为下划线
        return fileName.replaceAll("[\\\\/:*?\"<>|]", "_");
    }
}