package com.ruoyi.jarvis.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.jarvis.config.JarvisGoofishProperties;
import com.ruoyi.jarvis.domain.ErpGoofishOrder;
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLog;
import com.ruoyi.jarvis.domain.JDOrder;
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLogQuery;
import com.ruoyi.jarvis.domain.ErpOpenConfig;
import com.ruoyi.jarvis.dto.GoofishNotifyMessage;
import com.ruoyi.jarvis.dto.GoofishRrsLogisticsStatsVo;
import com.ruoyi.jarvis.dto.GoofishShipPreviewVo;
import com.ruoyi.jarvis.mapper.ErpGoofishOrderEventLogMapper;
import com.ruoyi.jarvis.mapper.ErpGoofishOrderMapper;
import com.ruoyi.jarvis.service.IErpGoofishOrderService;
import com.ruoyi.jarvis.service.IJDOrderService;
import com.ruoyi.jarvis.service.IErpOpenConfigService;
import com.ruoyi.jarvis.service.goofish.GoofishNotifyAsyncFacade;
import com.ruoyi.jarvis.service.goofish.GoofishOrderChangeLogger;
import com.ruoyi.jarvis.service.goofish.GoofishOrderPipeline;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ruoyi.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;

@Service
public class ErpGoofishOrderServiceImpl implements IErpGoofishOrderService {

    private static final Logger log = LoggerFactory.getLogger(ErpGoofishOrderServiceImpl.class);

    @Autowired
    private ObjectProvider<RocketMQTemplate> rocketMQTemplate;

    @Resource
    private JarvisGoofishProperties goofishProperties;

    @Resource
    private GoofishNotifyAsyncFacade goofishNotifyAsyncFacade;

    @Resource
    private GoofishOrderPipeline goofishOrderPipeline;

    @Resource
    private ErpGoofishOrderMapper erpGoofishOrderMapper;

    @Resource
    private ErpGoofishOrderEventLogMapper erpGoofishOrderEventLogMapper;

    @Resource
    private IErpOpenConfigService erpOpenConfigService;

    @Resource
    private GoofishOrderChangeLogger goofishOrderChangeLogger;

    @Resource
    private IJDOrderService jdOrderService;

    @Override
    public void publishOrProcessNotify(String appid, Long timestamp, JSONObject body) {
        RocketMQTemplate mq = rocketMQTemplate.getIfAvailable();
        if (mq != null) {
            GoofishNotifyMessage m = new GoofishNotifyMessage();
            m.setAppid(appid);
            m.setTimestamp(timestamp);
            m.setBody(body.toJSONString());
            mq.syncSend(goofishProperties.getMqTopic(), JSON.toJSONString(m));
        } else {
            goofishNotifyAsyncFacade.afterNotify(appid, body);
        }
    }

    @Override
    public void asyncPipelineAfterNotify(String appid, JSONObject notifyBody) {
        goofishOrderPipeline.runFullPipeline(appid, notifyBody);
    }

    @Override
    public GoofishRrsLogisticsStatsVo selectRrsJdLinkedLogisticsStats() {
        GoofishRrsLogisticsStatsVo vo = erpGoofishOrderMapper.selectRrsJdLinkedLogisticsStats();
        return vo != null ? vo : new GoofishRrsLogisticsStatsVo();
    }

    @Override
    public List<ErpGoofishOrder> selectList(ErpGoofishOrder query) {
        return erpGoofishOrderMapper.selectList(query);
    }

    @Override
    public ErpGoofishOrder selectById(Long id) {
        return erpGoofishOrderMapper.selectById(id);
    }

    @Override
    public int pullOrdersForAppKey(String appKey, int lookbackHours) {
        return goofishOrderPipeline.pullForAppKey(appKey, lookbackHours);
    }

    @Override
    public int pullAllEnabled(int lookbackHours) {
        int total = 0;
        List<ErpOpenConfig> cfgs = erpOpenConfigService.selectEnabledOrderBySort();
        if (cfgs == null) {
            return 0;
        }
        for (ErpOpenConfig c : cfgs) {
            if (c.getAppKey() == null) {
                continue;
            }
            total += goofishOrderPipeline.pullForAppKey(c.getAppKey(), lookbackHours);
        }
        return total;
    }

    @Override
    public int pullOrdersForAppKeyFullHistory(String appKey) {
        return goofishOrderPipeline.pullForAppKeyFullHistory(appKey);
    }

    @Override
    public int pullAllEnabledFullHistory() {
        int total = 0;
        List<ErpOpenConfig> cfgs = erpOpenConfigService.selectEnabledOrderBySort();
        if (cfgs == null) {
            return 0;
        }
        for (ErpOpenConfig c : cfgs) {
            if (c.getAppKey() == null) {
                continue;
            }
            total += goofishOrderPipeline.pullForAppKeyFullHistory(c.getAppKey());
        }
        return total;
    }

    @Override
    public void refreshDetail(Long id) {
        ErpGoofishOrder row = erpGoofishOrderMapper.selectById(id);
        if (row != null) {
            goofishOrderPipeline.refreshDetail(row);
        }
    }

    @Override
    public GoofishShipPreviewVo shipPreview(Long id) {
        ErpGoofishOrder row = erpGoofishOrderMapper.selectById(id);
        if (row == null) {
            GoofishShipPreviewVo empty = new GoofishShipPreviewVo();
            empty.setCompareHint("订单不存在");
            return empty;
        }
        return goofishOrderPipeline.buildShipPreview(row);
    }

    @Override
    public void retryShip(Long id) {
        erpGoofishOrderMapper.resetShipForRetry(id);
        ErpGoofishOrder row = erpGoofishOrderMapper.selectById(id);
        if (row != null) {
            goofishOrderPipeline.refreshDetail(row);
            goofishOrderPipeline.tryLinkJdOrder(row);
            goofishOrderPipeline.syncWaybillFromRedis(row);
            goofishOrderPipeline.tryAutoShip(row, true);
        }
    }

    @Override
    public int syncWaybillAndTryShipBatch(int limit) {
        return goofishOrderPipeline.syncWaybillAndTryShipBatch(limit);
    }

    @Override
    public void applyListOrNotifyItem(String appKey, JSONObject item, String lastNotifyJson) {
        goofishOrderPipeline.applyListOrNotifyItem(appKey, item, lastNotifyJson);
    }

    @Override
    public void notifyJdWaybillReady(Long jdOrderId) {
        if (jdOrderId == null) {
            return;
        }
        JDOrder jd = jdOrderService.selectJDOrderById(jdOrderId);
        LinkedHashSet<Long> processedGoofishPk = new LinkedHashSet<>();

        ErpGoofishOrder queryByJd = new ErpGoofishOrder();
        queryByJd.setJdOrderId(jdOrderId);
        List<ErpGoofishOrder> linked = erpGoofishOrderMapper.selectList(queryByJd);
        if (linked != null) {
            for (ErpGoofishOrder ref : linked) {
                processGoofishWaybillSyncAfterJdReady(ref.getId(), processedGoofishPk);
            }
        }

        if (jd != null && org.springframework.util.StringUtils.hasText(jd.getThirdPartyOrderNo())
            && isFxianyuDistributionMark(jd.getDistributionMark())) {
            List<ErpGoofishOrder> byNo =
                erpGoofishOrderMapper.selectByGoofishOrderNo(jd.getThirdPartyOrderNo().trim());
            if (byNo != null) {
                for (ErpGoofishOrder ref : byNo) {
                    ErpGoofishOrder full = erpGoofishOrderMapper.selectById(ref.getId());
                    if (full == null) {
                        continue;
                    }
                    if (full.getJdOrderId() != null && !full.getJdOrderId().equals(jdOrderId)) {
                        log.warn(
                            "闲鱼单 {} 已关联本地 jd_order_id={}，与本次京东单行主键 {} 不一致，跳过补绑",
                            full.getOrderNo(), full.getJdOrderId(), jdOrderId);
                        continue;
                    }
                    if (full.getJdOrderId() == null) {
                        attachGoofishToJdOrder(full.getId(), jdOrderId);
                    }
                    processGoofishWaybillSyncAfterJdReady(ref.getId(), processedGoofishPk);
                }
            }
        }
    }

    /** 单次：读库、同步 Redis 运单（含镜像 key）、尽力自动发货 */
    private void processGoofishWaybillSyncAfterJdReady(Long erpGoofishPk,
        LinkedHashSet<Long> processedGoofishPk) {
        if (erpGoofishPk == null || processedGoofishPk.contains(erpGoofishPk)) {
            return;
        }
        ErpGoofishOrder full = erpGoofishOrderMapper.selectById(erpGoofishPk);
        if (full == null) {
            return;
        }
        goofishOrderPipeline.syncWaybillFromRedis(full);
        goofishOrderPipeline.tryAutoShip(full);
        processedGoofishPk.add(erpGoofishPk);
    }

    private void attachGoofishToJdOrder(long erpGoofishPk, long jdOrderDbId) {
        ErpGoofishOrder p = new ErpGoofishOrder();
        p.setId(erpGoofishPk);
        p.setJdOrderId(jdOrderDbId);
        p.setUpdateTime(DateUtils.getNowDate());
        erpGoofishOrderMapper.update(p);
    }

    private static boolean isFxianyuDistributionMark(String distributionMark) {
        if (!org.springframework.util.StringUtils.hasText(distributionMark)) {
            return false;
        }
        String m = distributionMark.trim();
        return m.startsWith("F") || m.contains("\u95f2\u9c7c");
    }

    @Override
    public boolean hasLinkedGoofishOrder(Long jdOrderId) {
        if (jdOrderId == null) {
            return false;
        }
        ErpGoofishOrder query = new ErpGoofishOrder();
        query.setJdOrderId(jdOrderId);
        List<ErpGoofishOrder> list = erpGoofishOrderMapper.selectList(query);
        return list != null && !list.isEmpty();
    }

    @Override
    public void traceJdLogisticsPushForGoofish(Long jdOrderId, String waybillNo, String summary) {
        if (jdOrderId == null || goofishOrderChangeLogger == null) {
            return;
        }
        JDOrder jd = jdOrderService.selectJDOrderById(jdOrderId);
        LinkedHashSet<Long> ids = resolveGoofishRowIdsForJdLogisticsEvent(jdOrderId, jd);
        if (ids.isEmpty()) {
            return;
        }
        String wb = waybillNo != null ? waybillNo.trim() : "";
        String sum = summary != null ? summary : "";
        String msg = "京东订单 " + jdOrderId + "，运单 " + wb + "；" + sum;
        if (msg.length() > 1000) {
            msg = msg.substring(0, 999) + "…";
        }
        for (Long oid : ids) {
            ErpGoofishOrder row = erpGoofishOrderMapper.selectById(oid);
            if (row == null || row.getId() == null) {
                continue;
            }
            goofishOrderChangeLogger.append(row.getId(), row.getAppKey(), row.getOrderNo(),
                GoofishOrderChangeLogger.TYPE_LOGISTICS, GoofishOrderChangeLogger.SOURCE_JD_LOGISTICS_PUSH, msg);
        }
    }

    private LinkedHashSet<Long> resolveGoofishRowIdsForJdLogisticsEvent(Long jdOrderId, JDOrder jd) {
        LinkedHashSet<Long> ids = new LinkedHashSet<>();
        ErpGoofishOrder q = new ErpGoofishOrder();
        q.setJdOrderId(jdOrderId);
        List<ErpGoofishOrder> linked = erpGoofishOrderMapper.selectList(q);
        if (linked != null) {
            for (ErpGoofishOrder r : linked) {
                if (r.getId() != null) {
                    ids.add(r.getId());
                }
            }
        }
        if (jd != null && org.springframework.util.StringUtils.hasText(jd.getThirdPartyOrderNo())
            && isFxianyuDistributionMark(jd.getDistributionMark())) {
            List<ErpGoofishOrder> byNo =
                erpGoofishOrderMapper.selectByGoofishOrderNo(jd.getThirdPartyOrderNo().trim());
            if (byNo != null) {
                for (ErpGoofishOrder r : byNo) {
                    if (r.getId() != null) {
                        ids.add(r.getId());
                    }
                }
            }
        }
        return ids;
    }

    @Override
    public List<ErpGoofishOrderEventLog> listEventLogsByOrderId(Long orderId) {
        if (orderId == null) {
            return Collections.emptyList();
        }
        List<ErpGoofishOrderEventLog> list = erpGoofishOrderEventLogMapper.selectByOrderId(orderId);
        return list != null ? list : Collections.emptyList();
    }

    @Override
    public List<ErpGoofishOrderEventLog> selectEventLogList(ErpGoofishOrderEventLogQuery query) {
        if (query == null) {
            query = new ErpGoofishOrderEventLogQuery();
        }
        List<ErpGoofishOrderEventLog> list = erpGoofishOrderEventLogMapper.selectLogList(query);
        return list != null ? list : Collections.emptyList();
    }
}
