package com.zbf.web.mqtt;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zbf.common.utils.bean.BeanUtils;
import com.zbf.system.domain.*;
import com.zbf.system.mapper.InventoryCheckMapper;
import com.zbf.system.mapper.TBaseGoodsMapper;
import com.zbf.system.mapper.TBasePalletMapper;
import com.zbf.system.mapper.TMiStockMapper;
import com.zbf.system.service.impl.TStockCheckServiceImpl;
import com.zbf.web.util.Check;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component
public class MqttMessageHandler {

    @Autowired
    private TMiStockMapper mapper;

    @Autowired
    private InventoryCheckMapper inventoryCheckMapper;

    @Autowired
    private TStockCheckServiceImpl stockCheckService;

    @Autowired
    private TBaseGoodsMapper stockCheckMapper;

    @Autowired
    private TBasePalletMapper basePalletMapper;

    @Autowired
    private MqttConfig mqttConfig;

    @Autowired
    private Environment env;

    public void handleMessage(String topic, String payload) {
        try {
            JSONObject message = JSON.parseObject(payload);
            String method = message.getString("method");

            switch (method) {
                case "inventory":
                    processInventoryMessage(message);
                    break;
                case "setPoint":
                    processSetPointMessage(message);
                    break;
                case "go":
                    goMessage(message);
                    break;
                default:
                    log.warn("未知的消息类型: {}", method);
            }
        } catch (Exception e) {
            log.error("消息处理失败: {}", payload, e);
        }
    }

    private void goMessage(JSONObject message) {
        log.warn("go: {}", message);
    }

    @Transactional
    public void processInventoryMessage(JSONObject message) {
        try {
            String dateString = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            JSONArray params = message.getJSONArray("params");

            if (params == null || params.isEmpty()) {
                log.warn("未收到有效的盘点数据");
                return;
            }

            JSONObject data = params.getJSONObject(0);
            String wq = data.getString("wp");
            JSONArray tagsArray = data.getJSONArray("tags");

            if (tagsArray == null || tagsArray.isEmpty()) {
                log.warn("未检测到标签数据");
                return;
            }

            // 处理标签数据
            List<TBasePallet> pallets = new ArrayList<>();
            List<String> identifiers = new ArrayList<>();

            for (int i = 0; i < tagsArray.size(); i++) {
                JSONObject tagObj = tagsArray.getJSONObject(i);
                String epc = tagObj.getString("epc");
                String tid = tagObj.getString("tid");

                TBasePallet tBasePallet = new TBasePallet();
                tBasePallet.setPalletEpc(epc);
                tBasePallet.setPalletId(tid);
                pallets.add(tBasePallet);
                identifiers.add(tid);

                // 只在一楼模式下更新EPC
                if ("1".equals(wq)) {
                    basePalletMapper.updateEcp(tBasePallet);
                }
            }

            if (pallets.isEmpty()) {
                log.warn("未处理到有效的标签数据");
                return;
            }

            // 获取库存数据
            List<TMiStock> tMiStocks;
            String type;

            if ("1".equals(wq)) {
                // 一楼逻辑
                type = "一楼";
                LambdaQueryWrapper<TMiStock> wrapper = new LambdaQueryWrapper<>();
                wrapper.in(TMiStock::getCtl, identifiers);
                tMiStocks = mapper.selectList(wrapper);
            } else if ("2".equals(wq) || "3".equals(wq)) {
                // 二楼和抽盘逻辑
                type = "2".equals(wq) ? "二楼" : "抽盘";
                LambdaQueryWrapper<TBaseGoods> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.in(TBaseGoods::getGoodsTid, identifiers);
                List<String> goodsIds = stockCheckMapper.selectList(queryWrapper)
                        .stream()
                        .map(TBaseGoods::getGoodsId)
                        .collect(Collectors.toList());

                if (goodsIds.isEmpty()) {
                    log.warn("未找到对应的商品信息");
                    return;
                }

                LambdaQueryWrapper<TMiStock> wrapper = new LambdaQueryWrapper<>();
                wrapper.in(TMiStock::getGoodsId, goodsIds);
                tMiStocks = mapper.selectList(wrapper);
            } else {
                log.warn("无效的盘点类型: {}", wq);
                return;
            }

            if (tMiStocks.isEmpty()) {
                log.warn("未找到对应的库存数据");
                return;
            }

            log.info("收到盘点数据 -> 时间: {}, 标签数量: {}, 盘点类型：{}", dateString, pallets.size(), type);
            log.info("库存数据数量: {}", tMiStocks.size());

            // 创建盘点记录
            String checkId = Check.generateUniqueId();
            InventoryCheck inventoryCheck = new InventoryCheck();
            inventoryCheck.setCheckTime(dateString);
            inventoryCheck.setCheckType(type);
            inventoryCheck.setTaskNumber(checkId);
            inventoryCheckMapper.insertInventoryCheck(inventoryCheck);

            // 批量保存盘点数据
            List<TStockCheck> stockChecks = new ArrayList<>();
            for (TMiStock stock : tMiStocks) {
                TStockCheck stockCheck = new TStockCheck();
                BeanUtils.copyProperties(stock, stockCheck);
                stockCheck.setCheckId(checkId);
                // 处理日期格式
                if (stock.getPlanDate() != null && stock.getPlanDate().length() > 10) {
                    stockCheck.setPlanDate(stock.getPlanDate().substring(0, 10));
                }
                // 处理数值精度
                if (stock.getShelvesNum() != null) {
                    stockCheck.setShelvesNum(new BigDecimal(String.valueOf(stock.getShelvesNum()))
                            .setScale(3, RoundingMode.HALF_UP));
                }
                stockChecks.add(stockCheck);
            }

            // 分批保存数据
            if (!stockChecks.isEmpty()) {
                try {
                    stockCheckService.saveBatch(stockChecks);
                    log.info("盘点数据处理完成，共保存 {} 条记录", stockChecks.size());
                } catch (Exception e) {
                    log.error("保存盘点数据失败: {}", e.getMessage());
                    throw new RuntimeException("保存盘点数据失败", e);
                }
            }

        } catch (Exception e) {
            log.error("处理inventory消息时发生错误: {}", e.getMessage(), e);
            throw new RuntimeException("盘点数据处理失败", e);
        }
    }

    private void processSetPointMessage(JSONObject message) {
        log.info("处理setPoint消息: {}", message);
        // TODO: 在这里添加处理setPoint消息的具体逻辑
    }

    private String formatDateTimeString(String dateTimeStr) {
        try {
            // 验证输入长度
            if (dateTimeStr == null || dateTimeStr.length() != 14) {
                log.error("无效的日期时间字符串: {}", dateTimeStr);
                return "Invalid date format";
            }

            // 使用 SimpleDateFormat 进行转换
            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            Date date = inputFormat.parse(dateTimeStr);
            return outputFormat.format(date);

        } catch (Exception e) {
            log.error("日期时间格式化失败: {}, 错误: {}", dateTimeStr, e.getMessage());
            return "Format Error";
        }
    }

    /**
     * 发送 MQTT 消息
     * @param topicKey 配置文件中定义的主题 key
     * @param payload 消息内容
     */
    /*public void sendMessage(String topicKey, String payload) {
        try {
            String topic = env.getProperty("mqtt.topic." + topicKey);
            if (topic == null) {
                log.error("未找到主题配置: {}", topicKey);
                return;
            }

            MqttMessage message = new MqttMessage(payload.getBytes());
            mqttConfig.sendMessage(topic, message);
            log.info("消息已发送到主题 {}: {}", topic, payload);
        } catch (MqttException e) {
            log.error("发送消息失败: {}", e.getMessage(), e);
        }
    }*/
}