package modules.order;

import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import common.jfinal.AppConfig;
import common.model.Nftt;
import common.model.Order;
import common.model.OrderLog;
import common.model.User;
import common.utils.bsn.BsnSDK;
import modules.user.UserService;
import modules.user.UserTeamShareTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.TimeUnit;

public class OrderStatusMaintenanceTask implements Runnable {
    private static final Logger LOGGER = LoggerFactory.getLogger(OrderStatusMaintenanceTask.class);

    // 通过构造函数注入
    OrderService orderService;
    UserService userService;

    // 任务是否应该停止的标志
    private volatile boolean running = true; // 使用 volatile 确保多线程可见性
    
    public OrderStatusMaintenanceTask(OrderService orderService, UserService userService) {
        this.orderService = orderService;
        this.userService = userService;
        
        LOGGER.info("OrderStatusMaintenanceTask 实例已创建，注入 OrderService。{}", orderService.hashCode());
    }
    
    @Override
    public void run() {
        LOGGER.info("OrderStatusMaintenanceTask 后台任务开始运行...");
        while (running) { // 循环直到收到停止指令
            try {
                // 每次循环后休眠一段时间，避免CPU空转，并控制检查频率
                Thread.sleep(TimeUnit.SECONDS.toMillis(10)); // 每 10 秒检查一次
                
                // 只处理已支付但未确权的
                String sql = "SELECT id FROM t_order" +
                        " WHERE order_status=40";
                doNftTransfer(Order.dao.find(sql));
            } catch (InterruptedException e) {
                LOGGER.warn("OrderStatusMaintenanceTask 因中断而停止。");
                Thread.currentThread().interrupt(); // 重新设置中断状态
                running = false; // 退出循环
            } catch (Exception e) {
                // 捕获所有其他异常，记录日志，但保持线程继续运行
                LOGGER.error("OrderStatusMaintenanceTask 执行异常: {}", e.getMessage(), e);
                // 可以在这里添加告警，或在短时间后重试
                try {
                    Thread.sleep(TimeUnit.SECONDS.toMillis(5)); // 发生错误时短暂休眠，避免错误日志刷屏
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    running = false;
                }
            }
        }
        LOGGER.info("OrderStatusMaintenanceTask 后台任务已停止运行。");
    }

    private void doNftTransfer(List<Order> orderList) throws InterruptedException {
        // 未给用户转账的进行转账
        for (Order o : orderList) {
            // 1秒最多检查1个订单，防止超频
            Thread.sleep(TimeUnit.SECONDS.toMillis(1));

            // 使用事务锁定
            Db.tx(() -> {
                Order order = Order.dao.findFirst("SELECT * FROM t_order WHERE id=? FOR UPDATE", o.getId());
                User user = User.dao.findById(order.getUserId());

                // 已经交付完成或交付失败就不用看状态了
                if (order.getOrderStatus() == OrderController.OrderStatus.COMPLETED.code
                        || order.getOrderStatus() == OrderController.OrderStatus.CANCELED.code
                        || order.getOrderStatus() == OrderController.OrderStatus.REFUNDED.code) {
                    return true;
                }
    
                // 已经执行过转账的查看是否确权，查看状态
                if (StrKit.notBlank(order.getBsnTransferCode())) {
                    try {
                        JSONObject searchResponse = BsnSDK.search(order.getBsnTransferCode());
    
                        if (searchResponse.getInteger("code") == 0) {
                            JSONObject data = searchResponse.getJSONObject("data");
    
                            // status为1时才是交付成功，其它要么是pending要么是交付失败
                            if (data.getInteger("status") == 1) {
                                OrderLog log = new OrderLog();
                                log.set("order_id", order.getId());
                                log.set("from_status", order.getOrderStatus());
                                log.set("to_status", OrderController.OrderStatus.COMPLETED.code);
                                log.set("operator_id", 0);
                                log.set("operator_type", 3);
                                log.set("change_reason", "系统确权成功");
                                log.set("create_time", System.currentTimeMillis());
                                log.save();
    
                                order.setOrderStatus(OrderController.OrderStatus.COMPLETED.code);// 该笔订单已完成
                                order.setBsnTransferStatus(searchResponse.toJSONString());
                                order.setNftMintStatus(4);// nft已确权转移
                                order.setDeliveryStatus(1);// 交付成功
                                order.setDeliveryTime(System.currentTimeMillis());
                                order.setRefundStatus(0);
                                order.setClosedTime(System.currentTimeMillis());
                                order.setUpdateTime(System.currentTimeMillis());
    
                                order.update();
                                AppConfig.LOGGER.info("该订单已确权：{}", order);
    
                                // 该用户如果没有标记为有效账户进行标记
                                if (user.getIsEffective() == 0) {
                                    user.setIsEffective(1);
                                    user.setEffectiveTime(System.currentTimeMillis());
                                    user.update();
                                }
    
                                // 异步执行分润过程
                                AppConfig.TaskScheduler.submit(new UserTeamShareTask(order, userService));
                            }
    
                            // status为2时是交付失败，自动执行退款
                            if (data.getInteger("status") == 2) {
                                // 记录日志
                                OrderLog log = new OrderLog();
                                log.set("order_id", order.getId());
                                log.set("from_status", order.getOrderStatus());
                                log.set("to_status", OrderController.OrderStatus.REFUNDED.code);
                                log.set("operator_id", 0);
                                log.set("operator_type", 3);
                                log.set("change_reason", "系统确权失败");
                                log.set("create_time", System.currentTimeMillis());
                                log.save();
    
                                // 更新用户余额
                                user.setBalance(user.getBalance() + order.getTotalPrice());
                                user.update();
    
                                // 更新订单状态
                                order.setOrderStatus(OrderController.OrderStatus.REFUNDED.code);// 该笔订单已退款
                                order.setBsnTransferStatus(searchResponse.toJSONString());
                                order.setNftMintStatus(2);// nft是铸造成功了的，但是确权失败
                                order.setDeliveryStatus(2);// 交付失败
                                order.setRefundStatus(2);// 退款成功
                                order.setClosedTime(System.currentTimeMillis());
                                order.setUpdateTime(System.currentTimeMillis());
                                order.update();
    
                                AppConfig.LOGGER.error("该订单确权失败：{}", order);
                            }
                        } else {
                            throw new RuntimeException(searchResponse.toJSONString());
                        }
                    } catch (Exception e) {
                        AppConfig.LOGGER.error("查询转账信息执行失败：{}", e.getMessage());
                    }
                }
                // 未转账的先进行转账
                else {
                    Nftt nftt = Nftt.dao.findById(order.getNfttId());
                    // 订单是预购订单并且：如果还未转为正式销售的nft先不转帐
                    if (order.getOrderType() == 2 && System.currentTimeMillis() < nftt.getBuyingStartTime()) {
                        return true;
                    }
    
                    // 转账参数整理
                    String address = user.getBsnAccountAddress();
                    int quantity = order.getQuantity();
                    String tokenId = nftt.getBsnTokenId();
                    String bsnTransferCode = "DLTBH_ORDER_" + order.getId();
    
                    try {
                        JSONObject transferResponse = BsnSDK.sendNft(address, quantity, tokenId, bsnTransferCode);
    
                        if (transferResponse.getInteger("code") == 0) {
                            order.setBsnTransferCode(bsnTransferCode);
    
                            order.update();

                            AppConfig.LOGGER.info("订单NFT转账已执行成功：{}", transferResponse);
                        } else {
                            throw new RuntimeException(transferResponse.toJSONString());
                        }
                    } catch (Exception e) {
                        AppConfig.LOGGER.error("转账执行失败：{}", e.getMessage());
                    }
                }
                
                return true;
            });
        }
    }
}
