<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="88px">
      <el-form-item label="发送人" prop="fromUserName">
        <el-input v-model="queryParams.fromUserName" placeholder="企微 UserID" clearable style="width: 140px" @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-select v-model="queryParams.status" placeholder="全部" clearable style="width: 120px">
          <el-option label="待扫描" value="PENDING" />
          <el-option label="等待运单/重试" value="WAITING" />
          <el-option label="已推送" value="PUSHED" />
          <el-option label="已放弃" value="ABANDONED" />
          <el-option label="历史补录" value="IMPORTED" />
          <el-option label="已取消" value="CANCELLED" />
        </el-select>
      </el-form-item>
      <el-form-item label="短链" prop="trackingUrl">
        <el-input v-model="queryParams.trackingUrl" placeholder="3.cn 片段" clearable style="width: 180px" @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item label="运单号" prop="waybillNo">
        <el-input v-model="queryParams.waybillNo" placeholder="模糊" clearable style="width: 120px" @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item label="备注" prop="userRemark">
        <el-input v-model="queryParams.userRemark" placeholder="模糊" clearable style="width: 160px" @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item label="入队时间">
        <el-date-picker
          v-model="dateRange"
          type="daterange"
          value-format="yyyy-MM-dd"
          range-separator="至"
          start-placeholder="开始"
          end-placeholder="结束"
          style="width: 240px"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-alert
      title="用于排查企微 3.cn 分享链物流：WAITING + no_waybill_yet 未出单；push_failed 推送未成功；ABANDONED 为当轮队列重试用尽，定时对账（一月内）会归零次数并重新入队；IMPORTED 为从「企微消息跟踪」补录留痕；CANCELLED 为已取消扫描（订单取消等），不再对账入队，队列弹出也会跳过。"
      type="info"
      :closable="false"
      show-icon
      class="mb8"
    />

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="el-icon-video-play"
          size="mini"
          :loading="drainQueueLoading"
          v-hasPermi="['jarvis:wecom:shareLinkLog:list']"
          @click="handleDrainQueueOnce"
        >执行待队列一轮</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="warning"
          plain
          icon="el-icon-upload2"
          size="mini"
          :loading="backfillLoading"
          v-hasPermi="['jarvis:wecom:shareLinkLog:import']"
          @click="handleBackfill"
        >从追踪补录历史</el-button>
      </el-col>
    </el-row>

    <el-table v-loading="loading" :data="list" border>
      <el-table-column label="ID" prop="id" width="72" />
      <el-table-column label="发送人" prop="fromUserName" width="120" show-overflow-tooltip />
      <el-table-column label="推送目标" prop="touserPush" width="140" show-overflow-tooltip />
      <el-table-column label="状态" prop="status" width="100" align="center">
        <template slot-scope="scope">
          <el-tag v-if="scope.row.status === 'PUSHED'" type="success" size="small">{{ scope.row.status }}</el-tag>
          <el-tag v-else-if="scope.row.status === 'WAITING'" type="warning" size="small">{{ scope.row.status }}</el-tag>
          <el-tag v-else-if="scope.row.status === 'ABANDONED'" type="danger" size="small">{{ scope.row.status }}</el-tag>
          <el-tag v-else-if="scope.row.status === 'IMPORTED'" type="info" size="small">{{ scope.row.status }}</el-tag>
          <el-tag v-else-if="scope.row.status === 'CANCELLED'" type="info" size="small">{{ scope.row.status }}</el-tag>
          <el-tag v-else type="info" size="small">{{ scope.row.status || '—' }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="扫描次数" prop="scanAttempts" width="88" align="center" />
      <el-table-column label="运单号" prop="waybillNo" width="140" show-overflow-tooltip />
      <el-table-column label="用户备注" prop="userRemark" min-width="160" show-overflow-tooltip />
      <el-table-column label="最近说明" prop="lastNote" min-width="140" show-overflow-tooltip />
      <el-table-column label="短链" prop="trackingUrl" min-width="160" show-overflow-tooltip />
      <el-table-column label="创建时间" prop="createTime" width="160">
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.createTime) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="248" align="center" fixed="right">
        <template slot-scope="scope">
          <el-button type="text" size="mini" icon="el-icon-view" @click="openDetail(scope.row)">详情</el-button>
          <el-button type="text" size="mini" icon="el-icon-truck" @click="handleFetchShareLink(scope.row)">获取物流</el-button>
          <el-button
            v-if="scope.row.status !== 'PUSHED' && scope.row.status !== 'CANCELLED'"
            type="text"
            size="mini"
            icon="el-icon-circle-close"
            @click="handleCancelJob(scope.row)"
          >取消扫描</el-button>
          <el-button type="text" size="mini" icon="el-icon-delete" @click="handleRemoveJob(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />

    <el-dialog title="获取物流信息（分享链）" :visible.sync="fetchLogisticsDialogVisible" width="720px" append-to-body @close="fetchLogisticsResult = null">
      <div v-loading="fetchLogisticsLoading">
        <el-alert
          v-if="fetchLogisticsResult"
          :title="fetchLogisticsResult.success ? '请求已完成' : '请求失败'"
          :type="fetchLogisticsResult.success ? 'success' : 'error'"
          :closable="false"
          show-icon
          class="mb8"
        />
        <el-form v-if="fetchLogisticsResult && fetchLogisticsResult.success" label-width="120px" size="small">
          <el-form-item label="jobKey"><span>{{ fetchLogisticsResult.jobKey }}</span></el-form-item>
          <el-form-item label="终端成功"><span>{{ fetchLogisticsResult.terminalSuccess }}</span>（已推送或已去重）</el-form-item>
          <el-form-item label="已发推送"><span>{{ fetchLogisticsResult.pushSent }}</span></el-form-item>
          <el-form-item label="运单号" v-if="fetchLogisticsResult.waybillNo"><span>{{ fetchLogisticsResult.waybillNo }}</span></el-form-item>
          <el-form-item label="说明" v-if="fetchLogisticsResult.adhocNote"><span>{{ fetchLogisticsResult.adhocNote }}</span></el-form-item>
          <el-form-item label="物流短链"><span style="word-break:break-all">{{ fetchLogisticsResult.logisticsLink }}</span></el-form-item>
          <el-form-item label="请求URL" v-if="fetchLogisticsResult.requestUrl">
            <el-input type="textarea" :rows="2" readonly :value="fetchLogisticsResult.requestUrl" />
          </el-form-item>
          <el-form-item label="健康检查" v-if="fetchLogisticsResult.healthOk != null">
            <span>{{ fetchLogisticsResult.healthOk }}</span>
            <span v-if="fetchLogisticsResult.healthMessage"> — {{ fetchLogisticsResult.healthMessage }}</span>
          </el-form-item>
          <el-form-item label="推送错误" v-if="fetchLogisticsResult.pushError">
            <el-input type="textarea" :rows="3" readonly :value="fetchLogisticsResult.pushError" />
          </el-form-item>
          <el-form-item label="返回（原始）" v-if="fetchLogisticsResult.responseRaw">
            <el-input type="textarea" :rows="5" readonly :value="fetchLogisticsResult.responseRaw" />
          </el-form-item>
          <el-form-item label="返回（解析）" v-if="fetchLogisticsResult.responseData">
            <el-input type="textarea" :rows="8" readonly :value="formatJson(fetchLogisticsResult.responseData)" />
          </el-form-item>
        </el-form>
        <el-form v-else-if="fetchLogisticsResult && !fetchLogisticsResult.success" label-width="100px" size="small">
          <el-form-item label="错误"><span>{{ fetchLogisticsResult.error }}</span></el-form-item>
        </el-form>
        <span v-else-if="fetchLogisticsLoading" style="color:#999">正在请求…</span>
      </div>
      <div slot="footer">
        <el-button @click="fetchLogisticsDialogVisible = false">关闭</el-button>
        <el-button type="primary" v-if="fetchLogisticsResult && fetchLogisticsResult.success" @click="copyFetchLogisticsResult">复制 JSON</el-button>
      </div>
    </el-dialog>

    <el-dialog title="任务详情" :visible.sync="detailOpen" width="720px" append-to-body>
      <el-descriptions v-if="detail" :column="1" border size="small">
        <el-descriptions-item label="jobKey">{{ detail.jobKey }}</el-descriptions-item>
        <el-descriptions-item label="发送人">{{ detail.fromUserName || '—' }}</el-descriptions-item>
        <el-descriptions-item label="推送接收人">{{ detail.touserPush || '—' }}</el-descriptions-item>
        <el-descriptions-item label="状态">{{ detail.status }}</el-descriptions-item>
        <el-descriptions-item label="扫描次数">{{ detail.scanAttempts }}</el-descriptions-item>
        <el-descriptions-item label="运单号">{{ detail.waybillNo || '—' }}</el-descriptions-item>
        <el-descriptions-item label="最近说明">{{ detail.lastNote || '—' }}</el-descriptions-item>
        <el-descriptions-item label="短链">
          <span style="word-break:break-all">{{ detail.trackingUrl }}</span>
        </el-descriptions-item>
        <el-descriptions-item label="用户备注">
          <pre class="trace-pre">{{ detail.userRemark || '（空）' }}</pre>
        </el-descriptions-item>
        <el-descriptions-item label="创建时间">{{ parseTime(detail.createTime) }}</el-descriptions-item>
        <el-descriptions-item label="更新时间">{{ parseTime(detail.updateTime) }}</el-descriptions-item>
      </el-descriptions>
    </el-dialog>
  </div>
</template>

<script>
import { listWecomShareLinkLogisticsJob, getWecomShareLinkLogisticsJob, backfillShareLinkLogisticsFromTrace, fetchShareLinkManually, drainShareLinkPendingQueueOnce, cancelWecomShareLinkJob, removeWecomShareLinkJob } from '@/api/jarvis/wecomShareLinkLogistics'

export default {
  name: 'WecomShareLinkLogistics',
  data() {
    return {
      backfillLoading: false,
      drainQueueLoading: false,
      fetchLogisticsDialogVisible: false,
      fetchLogisticsLoading: false,
      fetchLogisticsResult: null,
      loading: true,
      total: 0,
      list: [],
      dateRange: [],
      detailOpen: false,
      detail: null,
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        fromUserName: null,
        status: null,
        trackingUrl: null,
        waybillNo: null,
        userRemark: null
      }
    }
  },
  created() {
    this.getList()
  },
  methods: {
    getList() {
      this.loading = true
      const q = { ...this.queryParams, params: {} }
      if (this.dateRange && this.dateRange.length === 2) {
        q.params = { beginTime: this.dateRange[0], endTime: this.dateRange[1] }
      }
      listWecomShareLinkLogisticsJob(q).then(res => {
        this.list = res.rows
        this.total = res.total
        this.loading = false
      }).catch(() => { this.loading = false })
    },
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    resetQuery() {
      this.dateRange = []
      this.resetForm('queryForm')
      this.handleQuery()
    },
    openDetail(row) {
      getWecomShareLinkLogisticsJob(row.jobKey).then(res => {
        this.detail = res.data
        this.detailOpen = true
      })
    },
    formatJson(v) {
      if (v == null) return ''
      if (typeof v === 'string') return v
      try {
        return JSON.stringify(v, null, 2)
      } catch (e) {
        return String(v)
      }
    },
    async handleFetchShareLink(row) {
      if (!row.trackingUrl || !String(row.trackingUrl).trim()) {
        this.$message.warning('该任务暂无物流短链')
        return
      }
      this.fetchLogisticsDialogVisible = true
      this.fetchLogisticsLoading = true
      this.fetchLogisticsResult = null
      try {
        const res = await fetchShareLinkManually({ jobKey: row.jobKey })
        if (res.code === 200) {
          this.fetchLogisticsResult = { success: true, ...res.data }
          this.$message.success('已请求物流接口，列表状态已更新')
          this.getList()
        } else {
          this.fetchLogisticsResult = { success: false, error: res.msg || '失败' }
          this.$message.error(res.msg || '获取失败')
        }
      } catch (e) {
        this.fetchLogisticsResult = { success: false, error: e.message || '请求异常' }
        this.$message.error('获取物流失败: ' + (e.message || '未知错误'))
      } finally {
        this.fetchLogisticsLoading = false
      }
    },
    copyFetchLogisticsResult() {
      if (!this.fetchLogisticsResult) return
      const t = JSON.stringify(this.fetchLogisticsResult, null, 2)
      if (navigator.clipboard && window.isSecureContext) {
        navigator.clipboard.writeText(t).then(() => this.$message.success('已复制到剪贴板')).catch(() => this.fallbackCopy(t))
      } else {
        this.fallbackCopy(t)
      }
    },
    fallbackCopy(text) {
      const textArea = document.createElement('textarea')
      textArea.value = text
      textArea.style.position = 'fixed'
      textArea.style.left = '-999999px'
      document.body.appendChild(textArea)
      textArea.focus()
      textArea.select()
      try {
        document.execCommand('copy')
        this.$message.success('已复制到剪贴板')
      } catch (e) {
        this.$message.error('复制失败')
      }
      document.body.removeChild(textArea)
    },
    handleDrainQueueOnce() {
      this.$modal.confirm('立即执行一轮 Redis 待扫描队列（与定时任务末尾逻辑相同，每批条数受后端 adhoc-pending-batch-size 限制）？').then(() => {
        this.drainQueueLoading = true
        return drainShareLinkPendingQueueOnce()
      }).then(res => {
        const d = res.data || {}
        this.$modal.msgSuccess('已弹出处理 ' + (d.processedFromQueue != null ? d.processedFromQueue : 0) + ' 条')
        this.getList()
      }).catch(() => {}).finally(() => { this.drainQueueLoading = false })
    },
    handleBackfill() {
      this.$modal.confirm('从「企微消息跟踪」补录历史分享链任务（状态 IMPORTED），已存在的 jobKey 将跳过。是否继续？').then(() => {
        this.backfillLoading = true
        return backfillShareLinkLogisticsFromTrace()
      }).then(res => {
        const d = res.data || {}
        const parts = [
          '扫描 ' + (d.scannedRemarkDoneRows != null ? d.scannedRemarkDoneRows : '—') + ' 条',
          '新增 ' + (d.imported != null ? d.imported : 0),
          '跳过已有 ' + (d.skippedDuplicate != null ? d.skippedDuplicate : 0),
          '无短链 ' + (d.skippedNoUrl != null ? d.skippedNoUrl : 0)
        ]
        this.$modal.msgSuccess(parts.join('，'))
        this.getList()
      }).catch(() => {}).finally(() => { this.backfillLoading = false })
    },
    handleCancelJob(row) {
      const tip = '取消后该 3.cn 任务不再自动扫描/对账入队；若 Redis 队列里还有同一 jobKey，弹出时也会跳过。订单取消可选此操作。是否继续？'
      this.$modal.confirm(tip).then(() => cancelWecomShareLinkJob({ jobKey: row.jobKey, lastNote: 'order_cancel' })).then(() => {
        this.$modal.msgSuccess('已取消扫描')
        this.getList()
      }).catch(() => {})
    },
    handleRemoveJob(row) {
      this.$modal.confirm('将永久删除该任务行（jobKey=' + row.jobKey + '）。是否继续？').then(() => removeWecomShareLinkJob(row.jobKey)).then(() => {
        this.$modal.msgSuccess('已删除')
        this.getList()
      }).catch(() => {})
    }
  }
}
</script>

<style scoped>
.trace-pre {
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
  font-family: inherit;
  font-size: 13px;
  max-height: 280px;
  overflow: auto;
}
.mb8 {
  margin-bottom: 8px;
}
</style>
