package org.jebot.handler.impl.merchant;

import cn.hutool.core.date.DateUtil;
import com.pengrad.telegrambot.request.SendMessage;
import com.pengrad.telegrambot.response.SendResponse;
import lombok.extern.slf4j.Slf4j;
import org.jebot.constant.Constant;
import org.jebot.handler.AbstractHandler;
import org.jebot.handler.dto.BotMessage;
import org.jebot.models.jebot.BotAccountBook;
import org.jebot.models.jebot.BotGroup;
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 java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

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

@Slf4j
public class MerchantOneClickSettlementHandler extends AbstractHandler {

    private static final Pattern SETTLE_MCH_ID = Pattern.compile("^" + SETTLE_MCH + "[a-zA-Z0-9]*$");

    @Override
    public boolean msgHandler(BotMessage message) {

        if (!message.isUserAuthenticated()) {
            return false;
        }

        if (message.messageTextIsEmpty()) {
            return false;
        }

        //一键所有商户结算
        if (SETTLE_MCH.equals(message.getMessageText())) {
            Date endDate = getYesnight();
            Date todayMidnight = getTodayMidnight(endDate);
            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()) {
                List<Long> mchIds = mchGroups.stream().map(BotGroup::getDataId).collect(Collectors.toList());
                List<MchAccount> mchAccounts = handlerManager.getMchAccountRepository().findByMchIds(mchIds);
                if (mchAccounts.isEmpty()) {
                    return true;
                }
                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("]").append(": 商户不存在\n");
                        return false;
                    }
                    if (mchAccount.getStatus() != 1) {
                        messageText.append(mchAccount.getName()).append(": 商户状态异常\n");
                    }
                    //查询订单出账单
                    List<PayOrder> payOrderList = handlerManager.getPayOrderRepository().findSuccessPayOrderByMchIdAndCreateTime(mchGroup.getDataId(), todayMidnight, endDate);
                    if (payOrderList.isEmpty()) {
                        messageText.append(mchAccount.getName()).append(": 无订单数据\n");
                        return false;
                    }

                    if (SettlementMch(message, mchGroup, payOrderList, todayMidnight, endDate)) {
                        messageText.append(mchAccount.getName()).append(": 结算成功\n");
                    } else {
                        messageText.append(mchAccount.getName()).append(": 结算失败\n");
                    }

                    //防止发送消息过快
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        log.error(e.getMessage());
                        e.printStackTrace();
                    }

                }
                SendMessage sendMessage = new SendMessage(message.getMessage().chat().id(), messageText.toString());
                SendResponse execute = message.getTelegramBot().execute(sendMessage);
                if (!execute.isOk()) {
                    log.error("一键结算发送消息失败, 错误信息: {}", execute.description());
                } else {
                    //记录结算记录
                    log.info("一键结算发送消息成功, 群组ID: {}, 结算记录: {}", message.getMessage().chat().id(), messageText.toString());
                }
            } else {
                SendMessage sendMessage = new SendMessage(message.getMessage().chat().id(), "没有商户群组");
                SendResponse execute = message.getTelegramBot().execute(sendMessage);
                if (!execute.isOk()) {
                    log.error("一键结算发送消息失败, 错误信息: {}", execute.description());
                } else {
                    //记录结算记录
                    log.info("一键结算发送消息成功, 群组ID: {}, 结算记录: {}", message.getMessage().chat().id(), "没有商户群组");
                }
            }
            return true;
        }

        //结算指定商户
        if (SETTLE_MCH_ID.matcher(message.getMessageText()).find()) {
            Date endDate = getYesnight();
            Date todayMidnight = getTodayMidnight(endDate);
            Long mchId = Long.valueOf(message.getMessageText().replace(SETTLE_MCH, ""));
            BotGroup mchGroup = handlerManager.getGroupRepository().findBotGroupByDataIdAndDataType(mchId, DATA_TYPE_MERCHANT);
            if (mchGroup == null) {
                SendMessage sendMessage = new SendMessage(message.getMessage().chat().id(), "商户未绑定群组");
                message.getTelegramBot().execute(sendMessage);
                return true;
            }
            //判断商户是否存在
            MchAccount mchAccount = handlerManager.getMchAccountRepository().findByMchId(mchId);
            if (mchAccount == null) {
                SendMessage sendMessage = new SendMessage(message.getMessage().chat().id(), "商户不存在");
                message.getTelegramBot().execute(sendMessage);
                return true;
            }
            if (mchAccount.getStatus() != 1) {
                SendMessage sendMessage = new SendMessage(message.getMessage().chat().id(), "商户状态异常");
                message.getTelegramBot().execute(sendMessage);
                return true;
            }
            //查询订单出账单
            List<PayOrder> payOrderList = handlerManager.getPayOrderRepository().findSuccessPayOrderByMchIdAndCreateTime(mchGroup.getDataId(), todayMidnight, endDate);
            if (payOrderList.isEmpty()) {
                SendMessage sendMessage = new SendMessage(message.getMessage().chat().id(), "无订单数据");
                message.getTelegramBot().execute(sendMessage);
                return false;
            }

            if (SettlementMch(message, mchGroup, payOrderList, todayMidnight, endDate)) {
                SendMessage sendMessage = new SendMessage(message.getMessage().chat().id(), "结算成功");
                message.getTelegramBot().execute(sendMessage);
            } else {
                SendMessage sendMessage = new SendMessage(message.getMessage().chat().id(), "结算失败");
                message.getTelegramBot().execute(sendMessage);
            }
            return true;
        }


        //一键结算所有通道
        if (SETTLE_PASSAGE.equals(message.getMessageText())) {
            Date endDate = getYesnight();
            Date todayMidnight = getTodayMidnight(endDate);
            List<BotGroup> botGroups = handlerManager.getGroupRepository().findAllByAgentWarningThresholdOrPaymentWarningThresholdGreaterThanZero();
            List<BotGroup> mchGroups = botGroups.stream().filter(botGroup -> Constant.DATA_TYPE_CHANNEL.equals(botGroup.getDataType())).collect(Collectors.toList());
            if (!mchGroups.isEmpty()) {
                List<Long> mchIds = mchGroups.stream().map(BotGroup::getDataId).collect(Collectors.toList());
                List<PayPassage> mchAccounts = handlerManager.getPassageRepository().findByPassageIds(mchIds);
                if (mchAccounts.isEmpty()) {
                    return true;
                }
                Map<Long, PayPassage> mchAccountMap = mchAccounts.stream()
                        .collect(Collectors.toMap(PayPassage::getId, payPassage -> payPassage));
                StringBuilder messageText = new StringBuilder();
                for (BotGroup mchGroup : mchGroups) {
                    //判断商户是否存在
                    PayPassage mchAccount = mchAccountMap.get(mchGroup.getDataId());
                    if (mchAccount == null) {
                        messageText.append(mchGroup.getDataName()).append("[").append(mchGroup.getDataId()).append("]").append(": 通道不存在\n");
                        return false;
                    }
                    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");
                        return false;
                    }

                    if (SettlementPassage(message, mchGroup, payOrderList, todayMidnight, endDate)) {
                        messageText.append(mchAccount.getPassageName()).append(": 结算成功\n");
                    } else {
                        messageText.append(mchAccount.getPassageName()).append(": 结算失败\n");
                    }

                    //防止发送消息过快
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        log.error(e.getMessage());
                        e.printStackTrace();
                    }

                }
                SendMessage sendMessage = new SendMessage(message.getMessage().chat().id(), messageText.toString());
                SendResponse execute = message.getTelegramBot().execute(sendMessage);
                if (!execute.isOk()) {
                    log.error("一键通道结算发送消息失败, 错误信息: {}", execute.description());
                } else {
                    //记录结算记录
                    log.info("一键通道结算发送消息成功, 群组ID: {}, 结算记录: {}", message.getMessage().chat().id(), messageText.toString());
                }
            } else {
                SendMessage sendMessage = new SendMessage(message.getMessage().chat().id(), "没有通道群组");
                SendResponse execute = message.getTelegramBot().execute(sendMessage);
                if (!execute.isOk()) {
                    log.error("一键通道结算发送消息失败, 错误信息: {}", execute.description());
                } else {
                    //记录结算记录
                    log.info("一键通道结算发送消息成功, 群组ID: {}, 结算记录: {}", message.getMessage().chat().id(), "没有通道群组");
                }
            }
            return true;
        }

        return false;
    }



    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);
        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:{},群组名称:{},用户ID:{},用户名称:{},金额:{},错误信息:{}",
                        message.getBotGroup().getDataId(),
                        message.getBotGroup().getDataName(),
                        message.getBotUser().getUserId(),
                        message.getBotUser().getUserName(),
                        deductionAmount.doubleValue(),
                        e.getMessage());
                e.printStackTrace();
                sendMessage = new SendMessage(message.getMessage().chat().id(),
                        "下发处理失败,请手动处理");
            } finally {
                if (sendMessage != null) {
                    message.getTelegramBot().execute(sendMessage);
                    log.info("一键结算发送消息成功, 群组ID: {}, 结算记录: {}", message.getMessage().chat().id(), 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.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);

        // ================= 发送账单 =================
        SendMessage sendMessage = new SendMessage(mchGroup.getGroupId(), stringBuilder.toString());
        SendResponse execute = message.getTelegramBot().execute(sendMessage);
        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:{},群组名称:{},用户ID:{},用户名称:{},金额:{},错误信息:{}",
                        message.getBotGroup().getDataId(),
                        message.getBotGroup().getDataName(),
                        message.getBotUser().getUserId(),
                        message.getBotUser().getUserName(),
                        deductionAmount.doubleValue(),
                        e.getMessage());
                e.printStackTrace();
                sendMessage = new SendMessage(message.getMessage().chat().id(),
                        "下发处理失败,请手动处理");
            } finally {
                if (sendMessage != null) {
                    message.getTelegramBot().execute(sendMessage);
                    log.info("一键结算发送消息成功, 群组ID: {}, 结算记录: {}", message.getMessage().chat().id(), sendMessage);
                }
            }
            return true;
        }
    }

}
