package org.jebot.rest;

import cn.hutool.core.date.DateUtil;
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.request.SendMessage;
import com.pengrad.telegrambot.response.SendResponse;
import lombok.extern.slf4j.Slf4j;
import org.jebot.config.BotConfig;
import org.jebot.constant.Constant;
import org.jebot.handler.HandlerManager;
import org.jebot.handler.dto.BotMessage;
import org.jebot.models.jebot.BotAccountBook;
import org.jebot.models.jebot.BotGroup;
import org.jebot.models.jebot.BotUser;
import org.jebot.models.xxpay.MchAccount;
import org.jebot.models.xxpay.PayOrder;
import org.jebot.models.xxpay.PayPassage;
import org.jebot.service.dto.UpdateBalance;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.jebot.constant.Constant.*;
import static org.jebot.constant.Constant.AMOUNT_MOVE_POINT;
import static org.jebot.util.DateUtil.getTodayMidnight;
import static org.jebot.util.DateUtil.getYesnight;

@Slf4j
@RestController
public class BotRest {
    @Resource
    TelegramBot telegramBot;
    private final BotConfig botConfig;
    private final HandlerManager handlerManager;

    public BotRest(BotConfig botConfig, HandlerManager handlerManager) {
        this.botConfig = botConfig;
        this.handlerManager = handlerManager;
    }

    @GetMapping("/reload-bot")
    public String reloadBot(@RequestParam String newToken) {
        botConfig.reloadBot(newToken, handlerManager);
        return "TelegramBot 已成功重载";
    }

    //宝塔定时调用接口触发
    @GetMapping("/dailyChannelSettlement")
    public String dailyChannelSettlement() {
        log.info("定时任务开始：每日通道结算");

        Date endDate = getYesnight();
        Date todayMidnight = getTodayMidnight(endDate);

        // 获取所有有告警阈值的群组
        List<BotGroup> botGroups = handlerManager.getGroupRepository()
                .findAllByAgentWarningThresholdOrPaymentWarningThresholdGreaterThanZero();

        // 只保留通道类型群组
        List<BotGroup> mchGroups = botGroups.stream()
                .filter(botGroup -> DATA_TYPE_CHANNEL.equals(botGroup.getDataType()))
                .collect(Collectors.toList());

        if (mchGroups.isEmpty()) {
            log.info("没有通道群组");
            return "没有通道群组";
        }

        // 查询通道信息
        List<Long> mchIds = mchGroups.stream().map(BotGroup::getDataId).collect(Collectors.toList());
        List<PayPassage> mchAccounts = handlerManager.getPassageRepository().findByPassageIds(mchIds);
        if (mchAccounts.isEmpty()) {
            return "没有通道信息";
        }
        Map<Long, PayPassage> mchAccountMap = mchAccounts.stream()
                .collect(Collectors.toMap(PayPassage::getId, payPassage -> payPassage));

        for (BotGroup mchGroup : mchGroups) {
            BotMessage message = new BotMessage();
            message.setBotGroup(mchGroup);
            message.setTelegramBot(telegramBot);
            BotUser botUser = new BotUser();
            botUser.setUserName("接口");
            botUser.setUserId(1L);
            message.setBotUser(botUser);

            StringBuilder messageText = new StringBuilder();

            PayPassage mchAccount = mchAccountMap.get(mchGroup.getDataId());
            if (mchAccount == null) {
                messageText.append(mchGroup.getDataName())
                        .append("[").append(mchGroup.getDataId()).append("]")
                        .append(": 通道不存在\n");
                messageText.append("处理结束\n");
                sendMessageAndLog(message, messageText.toString());
                continue;  // 处理下一个群组
            }

            if (mchAccount.getStatus() != 1) {
                messageText.append(mchAccount.getPassageName()).append(": 通道状态异常\n");
            }

            // 查询订单
            List<PayOrder> payOrderList = handlerManager.getPayOrderRepository()
                    .findSuccessPayOrderByPassageIdAndCreateTime(mchGroup.getDataId(), todayMidnight, endDate);

//            if (payOrderList.isEmpty()) {
//                messageText.append(mchAccount.getPassageName()).append(": 无订单数据\n");
//                sendMessageAndLog(message, messageText.toString());
//                continue;  // 处理下一个群组
//            }

            // 执行结算
            SettlementPassage(message, mchGroup, payOrderList, todayMidnight, endDate);

            // 记录消息内容
            messageText.append("结算完成: ").append(mchAccount.getPassageName()).append("\n");

            // 防止发送消息过快
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                log.error("线程中断: {}", e.getMessage(), e);
            }

            sendMessageAndLog(message, messageText.toString());
        }

        return "每日通道结算调用结算成功";
    }

    /**
     * 发送消息并记录日志的工具方法
     */
    private void sendMessageAndLog(BotMessage message, String content) {
        SendMessage sendMessage = new SendMessage(message.getBotGroup().getDataId(), content);
        SendResponse execute = message.getTelegramBot().execute(sendMessage);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        }
        if (!execute.isOk()) {
            log.error("发送消息失败,群组ID: {}, 错误信息: {}", message.getBotGroup().getDataId(), execute.description());
        } else {
            log.info("发送消息成功, 群组ID: {}, 内容: {}", message.getBotGroup().getDataId(), content);
        }
    }


    //宝塔定时调用接口触发
    @GetMapping("/dailyMchSettlement")
    public String dailyMchSettlement() {
        log.info("定时任务开始：每日商户结算");

        Date endDate = getYesnight(); // 前一天 23:59:59
        Date todayMidnight = getTodayMidnight(endDate); // 前一天 00:00:00
        List<BotGroup> botGroups = handlerManager.getGroupRepository()
                .findAllByAgentWarningThresholdOrPaymentWarningThresholdGreaterThanZero();

        List<BotGroup> mchGroups = botGroups.stream()
                .filter(botGroup -> Constant.DATA_TYPE_MERCHANT.equals(botGroup.getDataType()))
                .collect(Collectors.toList());

        if (mchGroups.isEmpty()) {
            log.info("没有商户群组");
            return "没有商户群组";
        }

        List<Long> mchIds = mchGroups.stream().map(BotGroup::getDataId).collect(Collectors.toList());
        List<MchAccount> mchAccounts = handlerManager.getMchAccountRepository().findByMchIds(mchIds);

        if (mchAccounts.isEmpty()) {
            log.info("没有商户账户数据");
            return "没有商户账户数据";
        }

        Map<Long, MchAccount> mchAccountMap = mchAccounts.stream()
                .collect(Collectors.toMap(MchAccount::getMchId, mchAccount -> mchAccount));

        StringBuilder messageText = new StringBuilder();

        for (BotGroup mchGroup : mchGroups) {
            MchAccount mchAccount = mchAccountMap.get(mchGroup.getDataId());
            if (mchAccount == null) {
                messageText.append(mchGroup.getDataName()).append("[").append(mchGroup.getDataId()).append("]: 商户不存在\n");
                continue;
            }

            if (mchAccount.getStatus() != 1) {
                messageText.append(mchAccount.getName()).append(": 商户状态异常\n");
                continue;
            }

            List<PayOrder> payOrderList = handlerManager.getPayOrderRepository()
                    .findSuccessPayOrderByMchIdAndCreateTime(mchGroup.getDataId(), todayMidnight, endDate);

//            if (payOrderList.isEmpty()) {
//                messageText.append(mchAccount.getName()).append(": 无订单数据\n");
//                continue;
//            }
            BotMessage message = new BotMessage();
            message.setBotGroup(mchGroup);
            message.setTelegramBot(telegramBot);
            BotUser botUser = new BotUser();
            botUser.setUserName("接口");
            botUser.setUserId(1L);
            message.setBotUser(botUser);
//            if (SettlementMch(message, mchGroup, payOrderList, todayMidnight, endDate)) {
//                messageText.append(mchAccount.getName()).append(": 结算成功\n");
//            } else {
//                messageText.append(mchAccount.getName()).append(": 结算失败\n");
//            }
            SettlementMch(message, mchGroup, payOrderList, todayMidnight, endDate);

            // 防止发送消息过快
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                log.error(e.getMessage(), e);
            }
            // 发送结算结果到管理员群或指定群
            SendMessage sendMessage = new SendMessage(mchGroup.getGroupId(), messageText.toString());
            SendResponse execute = telegramBot.execute(sendMessage);
            if (!execute.isOk()) {
                log.error("每日结算发送消息失败, 错误信息: {}", execute.description());
            } else {
                log.info("每日结算发送消息成功, 结算记录: {}", messageText);
            }
        }
        return "每日商户结算调用结算成功";
    }


    private boolean SettlementMch(BotMessage message, BotGroup mchGroup, List<PayOrder> payOrderList, Date todayMidnight, Date endDate) {

        StringBuilder stringBuilder = new StringBuilder();

        // 计算总金额（未扣手续费）
        BigDecimal totalAmount = payOrderList.stream()
                .map(PayOrder::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 成功总笔数
        long totalOrders = payOrderList.size();

        // 扣除手续费后的总跑量
        BigDecimal totalAmountByMchRate = payOrderList.stream()
                .map(order -> BigDecimal.ONE
                        .subtract(order.getMchRate().movePointLeft(Constant.AMOUNT_MOVE_POINT))
                        .multiply(order.getAmount()))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        stringBuilder.append(DateUtil.formatDate(endDate)).append("账单,请核对:\n");
        stringBuilder.append("总跑量: ").append(totalAmount.movePointLeft(Constant.AMOUNT_MOVE_POINT).doubleValue()).append("\n");
        stringBuilder.append("成功笔数: ").append(totalOrders).append("\n");
        stringBuilder.append("扣除手续费总跑量: ").append(totalAmountByMchRate.movePointLeft(Constant.AMOUNT_MOVE_POINT).doubleValue()).append("\n");

        // 扣除金额（手续费）
        // 下发金额 = 总跑量 - 手续费
        BigDecimal deductionAmount = totalAmountByMchRate.movePointLeft(Constant.AMOUNT_MOVE_POINT);


        // ================= 按费率分组汇总 =================
        stringBuilder.append("按费率统计:\n");

        Map<BigDecimal, List<PayOrder>> groupedByMchRate = payOrderList.stream()
                .collect(Collectors.groupingBy(PayOrder::getMchRate));

        groupedByMchRate.entrySet().stream()
                .sorted(Map.Entry.comparingByKey()) // 按费率排序
                .forEach(entry -> {
                    BigDecimal mchRate = entry.getKey();
                    BigDecimal amount = entry.getValue().stream()
                            .map(PayOrder::getAmount)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);

                    stringBuilder.append("费率").append(mchRate.doubleValue())
                            .append(": ")
                            .append(amount.movePointLeft(Constant.AMOUNT_MOVE_POINT).doubleValue())
                            .append("\n");
                });

        // ================= 发送账单 =================
        SendMessage sendMessage = new SendMessage(mchGroup.getGroupId(), stringBuilder.toString());
        SendResponse execute = message.getTelegramBot().execute(sendMessage);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        }
        if (!execute.isOk()) {
            log.error("一键结算发送消息失败, 错误信息: {}", execute.description());
            return false;
        } else {
            // ================= 更新商户账本 =================
            BotAccountBook accountBook = handlerManager.getAccountBookRepository()
                    .findByBelongIdAndType(mchGroup.getDataId(), DATA_TYPE_MERCHANT);

            if (accountBook == null) {
                accountBook = new BotAccountBook();
                accountBook.setBelongId(mchGroup.getDataId());
                accountBook.setType(DATA_TYPE_MERCHANT);
                accountBook.setPaymentBalance(0);
                accountBook.setAgentBalance(0);
                handlerManager.getAccountBookRepository().save(accountBook);
            }

            log.info("一键结算发送消息成功, 群组ID: {}, 结算记录: {}", mchGroup.getGroupId(), stringBuilder.toString());

            double oldPaymentBalance = accountBook.getPaymentBalance();
            double newPaymentBalance = BigDecimal.valueOf(oldPaymentBalance)
                    .subtract(deductionAmount).doubleValue();

            BotMessage botMessage = new BotMessage();
            botMessage.setBotGroup(mchGroup);
            botMessage.setBotUser(message.getBotUser());

            try {
                UpdateBalance updateMerchantPaymentBalance = new UpdateBalance();
                updateMerchantPaymentBalance.setId(accountBook.getId());
                updateMerchantPaymentBalance.setOldBalance(oldPaymentBalance);
                updateMerchantPaymentBalance.setNewBalance(newPaymentBalance);
                updateMerchantPaymentBalance.setAmount(deductionAmount.doubleValue());
                updateMerchantPaymentBalance.setMessage(botMessage);

                handlerManager.getAccountBookService()
                        .updatePaymentBalanceByIdAndPaymentBalance(updateMerchantPaymentBalance);

                sendMessage = new SendMessage(mchGroup.getGroupId(),
                        String.format("下发提醒\n下发金额: %.2f\n下发前: %.2f\n下发后: %.2f",
                                deductionAmount.doubleValue(), oldPaymentBalance, newPaymentBalance));

            } catch (Exception e) {
                log.error("更新商户群组账本失败,群组ID:{},群组名称:{},金额:{},错误信息:{}",
                        message.getBotGroup().getDataId(),
                        message.getBotGroup().getDataName(),
                        deductionAmount.doubleValue(),
                        e.getMessage());
                e.printStackTrace();
                sendMessage = new SendMessage(message.getBotGroup().getDataId(),
                        "下发处理失败,请手动处理");
            } finally {
                if (sendMessage != null) {
                    message.getTelegramBot().execute(sendMessage);
                    log.info("一键结算发送消息成功, 结算记录: {}", sendMessage);
                }
            }
            return true;
        }

    }


    private boolean SettlementPassage(BotMessage message, BotGroup mchGroup, List<PayOrder> payOrderList, Date todayMidnight, Date endDate) {

        StringBuilder stringBuilder = new StringBuilder();

        // 计算总金额（未扣手续费）
        BigDecimal totalAmount = payOrderList.stream()
                .map(PayOrder::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 成功总笔数
        long totalOrders = payOrderList.size();

        // 扣除手续费后的总跑量
        BigDecimal totalAmountByMchRate = payOrderList.stream()
                .map(order -> BigDecimal.ONE
                        .subtract(order.getPayPassageRate().movePointLeft(AMOUNT_MOVE_POINT))
                        .multiply(order.getAmount()))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        stringBuilder.append(DateUtil.formatDate(endDate)).append("【" + mchGroup.getDataName() + "】账单,请核对:\n");
        stringBuilder.append("总跑量: ").append(totalAmount.movePointLeft(AMOUNT_MOVE_POINT).doubleValue()).append("\n");
        stringBuilder.append("成功笔数: ").append(totalOrders).append("\n");
        stringBuilder.append("扣除手续费总跑量: ").append(totalAmountByMchRate.movePointLeft(AMOUNT_MOVE_POINT).doubleValue()).append("\n");

        // 扣除金额（手续费）
        BigDecimal deductionAmount = totalAmountByMchRate.movePointLeft(AMOUNT_MOVE_POINT);

        // ================= 发送账单 =================
        SendMessage sendMessage = new SendMessage(mchGroup.getGroupId(), stringBuilder.toString());
        SendResponse execute = message.getTelegramBot().execute(sendMessage);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            log.error(e.getMessage(), e);
        }
        if (!execute.isOk()) {
            log.error("一键结算发送消息失败, 错误信息: {}", execute.description());
            return false;
        } else {
            BotAccountBook accountBook = handlerManager.getAccountBookRepository()
                    .findByBelongIdAndType(mchGroup.getDataId(), DATA_TYPE_CHANNEL);

            if (accountBook == null) {
                accountBook = new BotAccountBook();
                accountBook.setBelongId(mchGroup.getDataId());
                accountBook.setType(DATA_TYPE_CHANNEL);
                accountBook.setPaymentBalance(0);
                accountBook.setAgentBalance(0);
                handlerManager.getAccountBookRepository().save(accountBook);
            }

            log.info("一键结算发送消息成功, 群组ID: {}, 结算记录: {}", mchGroup.getGroupId(), stringBuilder.toString());

            // ============ 用缓存 Map 保存账本 ============
            Map<Long, BotAccountBook> accountBookCache = new HashMap<>();

            // 查询总下发账本
            BotAccountBook accountBookAll = handlerManager.getAccountBookRepository()
                    .findByBelongIdAndType(mchGroup.getGroupId(), DATA_TYPE_CHANNEL);
            if (accountBookAll != null) {
                accountBookCache.put(mchGroup.getGroupId(), accountBookAll);
            }

            // 查询子群账本，加入缓存
            List<BotGroup> botGroups = this.handlerManager.getGroupRepository()
                    .findAllByGroupIdAndDataType(mchGroup.getGroupId(), DATA_TYPE_CHANNEL);

            for (BotGroup botGroup : botGroups) {
                BotAccountBook accountBookChannel = handlerManager.getAccountBookRepository()
                        .findByBelongIdAndType(botGroup.getDataId(), DATA_TYPE_CHANNEL);
                if (accountBookChannel != null) {
                    accountBookCache.put(botGroup.getDataId(), accountBookChannel);
                }
            }

            // 计算 oldPaymentBalance
            double oldPaymentBalance = accountBookCache.values().stream()
                    .mapToDouble(BotAccountBook::getPaymentBalance)
                    .sum();

            double newPaymentBalance = BigDecimal.valueOf(oldPaymentBalance)
                    .subtract(deductionAmount).doubleValue();

            BotMessage botMessage = new BotMessage();
            botMessage.setBotGroup(mchGroup);
            botMessage.setBotUser(message.getBotUser());

            try {
                UpdateBalance updateMerchantPaymentBalance = new UpdateBalance();
                updateMerchantPaymentBalance.setId(accountBook.getId());
                updateMerchantPaymentBalance.setOldBalance(accountBook.getPaymentBalance());
                updateMerchantPaymentBalance.setNewBalance(BigDecimal.valueOf(accountBook.getPaymentBalance())
                        .subtract(deductionAmount).doubleValue());
                updateMerchantPaymentBalance.setAmount(deductionAmount.doubleValue());
                updateMerchantPaymentBalance.setMessage(botMessage);

                handlerManager.getAccountBookService()
                        .updatePaymentBalanceByIdAndPaymentBalance(updateMerchantPaymentBalance);
                handlerManager.getAccountBookRepository().flush();

                // 同步更新缓存里的账本对象
                accountBook.setPaymentBalance(
                        BigDecimal.valueOf(accountBook.getPaymentBalance())
                                .subtract(deductionAmount).doubleValue()
                );
                accountBookCache.put(mchGroup.getDataId(), accountBook);

                sendMessage = new SendMessage(mchGroup.getGroupId(),
                        String.format("下发提醒\n下发金额: %.2f\n下发前: %.2f\n下发后: %.2f",
                                deductionAmount.doubleValue(), oldPaymentBalance, newPaymentBalance));

            } catch (Exception e) {
                log.error("更新商户群组账本失败,群组ID:{},群组名称:{},用户ID:{},用户名称:{},金额:{},错误信息:{}",
                        message.getBotGroup().getDataId(),
                        message.getBotGroup().getDataName(),
                        message.getBotUser().getUserId(),
                        message.getBotUser().getUserName(),
                        deductionAmount.doubleValue(),
                        e.getMessage(), e);
                sendMessage = new SendMessage(message.getBotGroup().getDataId(),
                        "下发处理失败,请手动处理");
            } finally {
                if (sendMessage != null) {
                    message.getTelegramBot().execute(sendMessage);
                    log.info("一键结算发送消息成功, 结算记录: {}", sendMessage);
                }
            }
            return true;
        }
    }



}




