package com.ruoyi.web.controller.jarvis;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.jarvis.domain.WeComShareLinkLogisticsJob;
import com.ruoyi.jarvis.mapper.WeComShareLinkLogisticsJobMapper;
import com.ruoyi.jarvis.service.ILogisticsService;
import com.ruoyi.jarvis.service.IWeComShareLinkLogisticsJobService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/jarvis/wecom/shareLinkLogisticsJob")
public class WeComShareLinkLogisticsJobController extends BaseController {

    @Resource
    private IWeComShareLinkLogisticsJobService weComShareLinkLogisticsJobService;
    @Resource
    private ILogisticsService logisticsService;
    @Resource
    private WeComShareLinkLogisticsJobMapper weComShareLinkLogisticsJobMapper;

    @PreAuthorize("@ss.hasPermi('jarvis:wecom:shareLinkLog:list')")
    @GetMapping("/list")
    public TableDataInfo list(WeComShareLinkLogisticsJob query) {
        startPage();
        List<WeComShareLinkLogisticsJob> list = weComShareLinkLogisticsJobService.selectList(query);
        return getDataTable(list);
    }

    @PreAuthorize("@ss.hasPermi('jarvis:wecom:shareLinkLog:list')")
    @GetMapping("/{jobKey}")
    public AjaxResult getInfo(@PathVariable("jobKey") String jobKey) {
        return success(weComShareLinkLogisticsJobService.selectByJobKey(jobKey));
    }

    @PreAuthorize("@ss.hasPermi('jarvis:wecom:shareLinkLog:import')")
    @PostMapping("/backfillFromInboundTrace")
    public AjaxResult backfillFromInboundTrace() {
        Map<String, Object> r = weComShareLinkLogisticsJobService.backfillImportedFromInboundTrace();
        return success(r);
    }

    /**
     * 与订单列表「获取物流」一致：立即请求物流接口，有运单则推送分享链模板，并回写任务行。
     */
    @PreAuthorize("@ss.hasPermi('jarvis:wecom:shareLinkLog:list')")
    @PostMapping("/fetchShareLinkManually")
    public AjaxResult fetchShareLinkManually(@RequestBody Map<String, Object> body) {
        if (body == null || body.get("jobKey") == null) {
            return AjaxResult.error("jobKey 不能为空");
        }
        String jobKey = body.get("jobKey").toString().trim();
        if (!StringUtils.hasText(jobKey)) {
            return AjaxResult.error("jobKey 不能为空");
        }
        WeComShareLinkLogisticsJob job = weComShareLinkLogisticsJobService.selectByJobKey(jobKey);
        if (job == null) {
            return AjaxResult.error("任务不存在");
        }
        if ("CANCELLED".equalsIgnoreCase(job.getStatus())) {
            return AjaxResult.error("任务已取消扫描，请先恢复或新建任务");
        }
        if (!StringUtils.hasText(job.getTrackingUrl())) {
            return AjaxResult.error("该任务无物流短链");
        }
        String remark = job.getUserRemark() != null ? job.getUserRemark() : "";
        String touser = job.getTouserPush() != null ? job.getTouserPush() : "";
        Map<String, Object> data = logisticsService.adminFetchShareLinkLogisticsDebug(
            job.getTrackingUrl(), remark, touser);
        data.put("jobKey", jobKey);

        int successAttempts = job.getScanAttempts() == null ? 1 : job.getScanAttempts() + 1;
        String adhocNote = data.get("adhocNote") != null ? data.get("adhocNote").toString() : "";
        String note = "manual:" + adhocNote;
        if (Boolean.TRUE.equals(data.get("terminalSuccess"))) {
            String wb = data.get("waybillNo") != null ? data.get("waybillNo").toString() : null;
            weComShareLinkLogisticsJobMapper.updateByJobKey(jobKey, "PUSHED", note, successAttempts,
                StringUtils.hasText(wb) ? wb : null);
        } else {
            /* 失败仍走自动队列时，不得垫高 scan_attempts，否则 Redis attempts 与定时 drain 上限错位，未超限也会被放弃 */
            weComShareLinkLogisticsJobMapper.updateByJobKey(jobKey, "WAITING", note, job.getScanAttempts(), null);
            WeComShareLinkLogisticsJob refreshed = weComShareLinkLogisticsJobService.selectByJobKey(jobKey);
            if (refreshed != null) {
                logisticsService.pushShareLinkJobToRedis(refreshed);
            }
        }
        return AjaxResult.success(data);
    }

    /**
     * 手动执行一轮与定时任务相同的 Redis 待队列弹出（条数上限同 adhoc-pending-batch-size）。
     */
    @PreAuthorize("@ss.hasPermi('jarvis:wecom:shareLinkLog:list')")
    @PostMapping("/drainPendingQueueOnce")
    public AjaxResult drainPendingQueueOnce() {
        int n = logisticsService.drainPendingShareLinkQueue();
        Map<String, Object> r = new LinkedHashMap<>();
        r.put("processedFromQueue", n);
        r.put("hint", "为单次弹栈处理条数；每项内部仍可能因未出单重新入队");
        return AjaxResult.success(r);
    }

    /**
     * 订单取消等：标记为 CANCELLED，不再被定时对账入队；队列弹出时也会跳过物流请求与推送。
     */
    @PreAuthorize("@ss.hasPermi('jarvis:wecom:shareLinkLog:list')")
    @PostMapping("/cancel")
    public AjaxResult cancel(@RequestBody Map<String, Object> body) {
        if (body == null || body.get("jobKey") == null) {
            return AjaxResult.error("jobKey 不能为空");
        }
        String jobKey = body.get("jobKey").toString().trim();
        if (!StringUtils.hasText(jobKey)) {
            return AjaxResult.error("jobKey 不能为空");
        }
        WeComShareLinkLogisticsJob job = weComShareLinkLogisticsJobService.selectByJobKey(jobKey);
        if (job == null) {
            return AjaxResult.error("任务不存在");
        }
        if ("CANCELLED".equalsIgnoreCase(job.getStatus())) {
            return AjaxResult.success("已是取消状态");
        }
        String extra = body.get("lastNote") != null ? body.get("lastNote").toString().trim() : "";
        String note = "manual_cancel";
        if (StringUtils.hasText(extra)) {
            note = note + "|" + extra;
        }
        if (note.length() > 500) {
            note = note.substring(0, 500) + "…";
        }
        weComShareLinkLogisticsJobMapper.updateByJobKey(jobKey, "CANCELLED", note, null, null);
        return AjaxResult.success();
    }

    /**
     * 物理删除任务行（Redis 中已存在的同 jobKey 队列项仍可能被弹出，但会因库中无行而跳过扫描）。
     */
    @PreAuthorize("@ss.hasPermi('jarvis:wecom:shareLinkLog:list')")
    @DeleteMapping("/{jobKey}")
    public AjaxResult remove(@PathVariable("jobKey") String jobKey) {
        if (!StringUtils.hasText(jobKey)) {
            return AjaxResult.error("jobKey 不能为空");
        }
        weComShareLinkLogisticsJobMapper.deleteByJobKey(jobKey.trim());
        return AjaxResult.success();
    }
}
