package com.ruoyi.jarvis.service.impl;

import com.ruoyi.jarvis.domain.WeComInboundTrace;
import com.ruoyi.jarvis.domain.WeComShareLinkLogisticsJob;
import com.ruoyi.jarvis.mapper.WeComInboundTraceMapper;
import com.ruoyi.jarvis.mapper.WeComShareLinkLogisticsJobMapper;
import com.ruoyi.jarvis.service.ILogisticsService;
import com.ruoyi.jarvis.service.IWeComShareLinkLogisticsJobService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class WeComShareLinkLogisticsJobServiceImpl implements IWeComShareLinkLogisticsJobService {

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

    /** 与 WeComInboundServiceImpl.replyLogisticsRemarkDone 中文案一致 */
    private static final String REPLY_MARK_SHARE_LINK_DONE = "已加入查询队列";

    private static final Pattern JD_3CN_HTTPS = Pattern.compile("https://3\\.cn/[A-Za-z0-9\\-]+");
    private static final Pattern JD_3CN_HTTP = Pattern.compile("http://3\\.cn/[A-Za-z0-9\\-]+");

    @Resource
    private WeComShareLinkLogisticsJobMapper weComShareLinkLogisticsJobMapper;
    @Resource
    private WeComInboundTraceMapper weComInboundTraceMapper;

    @Resource
    private ILogisticsService logisticsService;

    @Override
    public WeComShareLinkLogisticsJob selectByJobKey(String jobKey) {
        return weComShareLinkLogisticsJobMapper.selectByJobKey(jobKey);
    }

    @Override
    public List<WeComShareLinkLogisticsJob> selectList(WeComShareLinkLogisticsJob query) {
        return weComShareLinkLogisticsJobMapper.selectWeComShareLinkLogisticsJobList(query);
    }

    @Override
    public List<WeComShareLinkLogisticsJob> selectRecentForInstruction(String remarkKeyword, int days, int limit) {
        int d = Math.max(1, Math.min(days, 365));
        int lim = Math.max(1, Math.min(limit, 100));
        String kw =
            remarkKeyword != null && !remarkKeyword.trim().isEmpty() ? remarkKeyword.trim() : null;
        return weComShareLinkLogisticsJobMapper.selectRecentForInstruction(kw, d, lim);
    }

    @Override
    public int deleteByJobKey(String jobKey) {
        if (jobKey == null || !StringUtils.hasText(jobKey.trim())) {
            return 0;
        }
        return weComShareLinkLogisticsJobMapper.deleteByJobKey(jobKey.trim());
    }

    @Override
    public int deleteByRemarkAndTrackingUrl(String remark, String trackingUrl) {
        if (!StringUtils.hasText(trackingUrl)) {
            return 0;
        }
        String r = remark != null ? remark : "";
        return weComShareLinkLogisticsJobMapper.deleteByRemarkAndTrackingUrl(r, trackingUrl.trim());
    }

    @Override
    public Map<String, Object> backfillImportedFromInboundTrace() {
        int imported = 0;
        int skippedDuplicate = 0;
        int skippedNoUrl = 0;
        int scanned = 0;

        List<WeComInboundTrace> traces = weComInboundTraceMapper.selectTracesShareLinkRemarkDone(REPLY_MARK_SHARE_LINK_DONE);
        if (traces != null) {
            for (WeComInboundTrace t : traces) {
                if (t == null || t.getId() == null || !StringUtils.hasText(t.getFromUserName())) {
                    continue;
                }
                scanned++;
                String jobKey = "tracebf" + t.getId();
                if (weComShareLinkLogisticsJobMapper.selectByJobKey(jobKey) != null) {
                    skippedDuplicate++;
                    continue;
                }
                String url = extractJd3cnUrl(t.getContent());
                if (url == null) {
                    WeComInboundTrace prior = weComInboundTraceMapper.selectLatestPriorTraceWith3cnLink(
                        t.getFromUserName(), t.getId());
                    if (prior != null) {
                        url = extractJd3cnUrl(prior.getContent());
                    }
                }
                if (!StringUtils.hasText(url)) {
                    skippedNoUrl++;
                    log.debug("补录跳过 traceId={} 无可用 3.cn", t.getId());
                    continue;
                }
                final String trackingUrlResolved = url.trim();

                WeComShareLinkLogisticsJob row = new WeComShareLinkLogisticsJob();
                row.setJobKey(jobKey);
                row.setFromUserName(t.getFromUserName().trim());
                row.setTrackingUrl(trackingUrlResolved);
                String remark = t.getContent() != null ? t.getContent() : "";
                row.setUserRemark(remark);
                row.setTouserPush(t.getFromUserName().trim());
                row.setStatus("IMPORTED");
                row.setScanAttempts(0);
                row.setLastNote("from_trace_id=" + t.getId());
                if (t.getCreateTime() != null) {
                    row.setCreateTime(t.getCreateTime());
                    row.setUpdateTime(t.getCreateTime());
                }
                try {
                    weComShareLinkLogisticsJobMapper.insertWeComShareLinkLogisticsJob(row);
                    imported++;
                    try {
                        logisticsService.pushShareLinkJobToRedis(row);
                    } catch (Exception e) {
                        log.warn("补录入队 Redis 失败 jobKey={} err={}", row.getJobKey(), e.toString());
                    }
                } catch (Exception e) {
                    log.warn("补录插入失败 traceId={} err={}", t.getId(), e.toString());
                }
            }
        }

        Map<String, Object> r = new LinkedHashMap<>();
        r.put("scannedRemarkDoneRows", scanned);
        r.put("imported", imported);
        r.put("skippedDuplicate", skippedDuplicate);
        r.put("skippedNoUrl", skippedNoUrl);
        r.put("hint", "IMPORTED 表示仅从企微消息追踪补录，运单与是否已推送以当时为准，可与 trace_id 对照 wecom_inbound_trace");
        return r;
    }

    private static String extractJd3cnUrl(String text) {
        if (!StringUtils.hasText(text)) {
            return null;
        }
        Matcher m = JD_3CN_HTTPS.matcher(text);
        if (m.find()) {
            return m.group();
        }
        Matcher m2 = JD_3CN_HTTP.matcher(text);
        if (m2.find()) {
            return m2.group();
        }
        return null;
    }
}
