<script>
  import { onMount } from "svelte";
  import { api, formatTime } from "../lib/api.js";
  import StatusBadge from "../lib/StatusBadge.svelte";
  import Icon from "../lib/Icon.svelte";

  let jobs = $state([]);
  let runs = $state({});
  let loading = $state(true);
  let error = $state("");
  let tick = $state(0);

  async function load() {
    loading = true;
    error = "";
    try {
      jobs = (await api("/api/jobs")).jobs;
      runs = Object.fromEntries(await Promise.all(jobs.map(async (job) => [
        job.id,
        await api(`/api/jobs/${encodeURIComponent(job.id)}/runs?limit=10`).then((value) => value.runs).catch(() => [])
      ])));
    } catch (caught) {
      error = caught.message;
    } finally {
      loading = false;
    }
  }

  function countdown(ts) {
    void tick;
    if (!ts) return "—";
    const ms = ts < 1e12 ? ts * 1000 : ts;
    const diff = ms - Date.now();
    if (diff <= 0) return "即将运行";
    const mins = Math.floor(diff / 60000);
    if (mins < 1) return "即将运行";
    if (mins < 60) return `${mins} 分钟后`;
    const hours = Math.floor(mins / 60);
    if (hours < 24) return `${hours} 小时后`;
    return `${Math.floor(hours / 24)} 天后`;
  }

  function dotColor(status) {
    if (status === "completed" || status === "success" || status === "ok") return "var(--signal)";
    if (status === "timed_out" || status === "unknown" || status === "interrupted") return "var(--accent)";
    if (status === "running") return "var(--info)";
    return "var(--danger)";
  }

  function scheduleLabel(schedule) {
    if (!schedule) return "—";
    if (schedule.type === "at") return `单次 · ${formatTime(schedule.at)}`;
    if (schedule.type === "every") return `每 ${Math.max(1, Math.round(schedule.every_ms / 60000))} 分钟`;
    if (schedule.type === "cron") return `${schedule.expr}${schedule.tz ? ` · ${schedule.tz}` : ""}`;
    return schedule.type || "—";
  }

  function deliveryLabel(policy) {
    return { always: "始终通知", on_alert: "异常通知", never: "从不通知" }[policy] || policy;
  }

  onMount(() => {
    load();
    const timer = setInterval(() => { tick += 1; }, 30000);
    return () => clearInterval(timer);
  });
</script>

<section class="page active content-page">
  <div class="toolbar">
    <div>
      <h2 style="margin:0">定时任务</h2>
      <p style="margin:2px 0 0;color:var(--muted);font-size:12px">查看统一的定时执行、结构化结果与通知状态；Agent 运行审计请到「子代理」页面。</p>
    </div>
    <button class="secondary" onclick={load}><Icon name="refresh" size={16} />刷新</button>
  </div>
  <div class="cards">
    {#if loading}<div class="loading">加载中…</div>
    {:else if error}<div class="empty-card error-text">{error}</div>
    {:else}
      {#each jobs as job (job.id)}
        <article class="card">
          <div class="card-row">
            <div>
              <h3>{job.name}</h3>
              <p>{job.prompt}</p>
              <div class="meta">
                <span class="mono cron">{scheduleLabel(job.schedule)}</span>
                <span>Agent：{job.agent_id || "Root"}</span>
                <span>投递：{deliveryLabel(job.delivery_policy)}</span>
                <span>{job.channel} · {job.chat_id}</span>
                <span>下次 {countdown(job.next_run_at)}</span>
                <span>上次 {formatTime(job.last_run_at)}</span>
              </div>
              {#if runs[job.id]?.length}
                <div class="status-dots">
                  {#each runs[job.id] as run}
                    <span class="dot" style="background:{dotColor(run.status)}" title="{run.status} {formatTime(run.finished_at)}"></span>
                  {/each}
                </div>
              {/if}
            </div>
            <StatusBadge status={job.enabled ? (job.last_outcome || "enabled") : "disabled"} />
          </div>
          {#if runs[job.id]?.length}
            <div class="details">
              {#each runs[job.id] as run}
                <details class="run-detail">
                  <summary class="run-row">
                    <span class="meta">{formatTime(run.finished_at || run.started_at || run.scheduled_for)} · {run.duration_ms ?? "—"}ms · outcome={run.outcome || "—"} · delivery={run.delivery_status} ({run.delivery_attempts})</span>
                    <StatusBadge status={run.status} />
                  </summary>
                  {#if run.message}<p><b>结果</b><br />{run.message}</p>{/if}
                  {#if run.diagnostic}<p class="diagnostic"><b>诊断</b><br />{run.diagnostic}</p>{/if}
                  {#if run.delivery_error}<p class="diagnostic"><b>投递错误</b><br />{run.delivery_error}</p>{/if}
                </details>
              {/each}
            </div>
          {/if}
        </article>
      {:else}<div class="empty-card">暂无定时任务</div>{/each}
    {/if}
  </div>
</section>

<style>
  .cron { font-size: 12px; color: var(--text-soft); background: var(--code-bg); padding: 1px 6px; border-radius: 4px; border: 1px solid var(--line); font-variant-numeric: tabular-nums; }
  .status-dots { display: flex; gap: 4px; margin-top: 6px; align-items: center; }
  .run-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .run-detail { padding: 7px 0; border-top: 1px solid var(--line); }
  .run-detail:first-child { border-top: 0; }
  .run-detail summary { cursor: pointer; justify-content: space-between; }
  .run-detail p { margin: 8px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 12px; color: var(--text-soft); }
  .run-detail .diagnostic { color: var(--danger); }
</style>
