"use client";

import { useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";

import { apiFetch } from "@/lib/api";
import { cardStyle, inputStyle, labelStyle, td, th } from "@/lib/adminStyles";

interface RunRow {
  run_id: number;
  started_at: string | null;
  finished_at: string | null;
  region_codes: number[];
  developer_ids: string[];
  objects_count: number | null;
  flats_count: number | null;
  requests_count: number | null;
  status: string;
  error: string | null;
  snapshot_date: string | null;
}

interface TriggerResp {
  task_id: string;
  region_code: number;
  developers: string[] | null;
}

interface QueueTask {
  worker: string;
  task_id: string;
  name: string | null;
  args: unknown[] | null;
  kwargs: Record<string, unknown> | null;
  time_start: number | null;
  eta: string | null;
}

interface QueueStatus {
  workers: string[];
  queue_depth: number | null;
  active: QueueTask[];
  reserved: QueueTask[];
  scheduled: QueueTask[];
}

interface LogRow {
  log_id: number;
  run_id: number | null;
  ts: string | null;
  level: "info" | "warn" | "error";
  stage: string | null;
  obj_id: number | null;
  message: string;
}

interface FailureRow {
  failure_id: number;
  run_id: number | null;
  obj_id: number | null;
  endpoint: string | null;
  full_url: string | null;
  http_status: number | null;
  error: string | null;
  body_preview: string | null;
  occurred_at: string | null;
}

export default function ScrapeAdminPage() {
  const [region, setRegion] = useState(66);
  const [devs, setDevs] = useState("");
  const [fetchFlats, setFetchFlats] = useState(true);
  const [extras, setExtras] = useState(true);
  const [downloadPhotos, setDownloadPhotos] = useState(false);
  const [forceRun, setForceRun] = useState(false);
  const [showFailures, setShowFailures] = useState(false);
  const [failuresRunId, setFailuresRunId] = useState<number | "">("");
  const [logsRunId, setLogsRunId] = useState<number | "">("");
  const queryClient = useQueryClient();

  const runs = useQuery({
    queryKey: ["scrape-runs"],
    queryFn: () => apiFetch<RunRow[]>("/api/v1/admin/scrape/runs?limit=20"),
    refetchInterval: 5000,
  });

  const trigger = useMutation({
    mutationFn: () =>
      apiFetch<TriggerResp>("/api/v1/admin/scrape/kn", {
        method: "POST",
        body: JSON.stringify({
          region_code: region,
          developers: devs
            ? devs
                .split(",")
                .map((s) => s.trim())
                .filter(Boolean)
            : null,
          fetch_flats: fetchFlats,
          extras,
          download_photos: downloadPhotos,
          force: forceRun,
        }),
      }),
    onSuccess: (data) => {
      console.log("[scrape] queued:", data);
      queryClient.invalidateQueries({ queryKey: ["scrape-runs"] });
    },
    onError: (err) => {
      console.error("[scrape] failed:", err);
    },
  });

  const releaseLock = useMutation({
    mutationFn: () =>
      apiFetch<{
        region_code: number;
        developers: string[] | null;
        released: boolean;
      }>("/api/v1/admin/scrape/release-lock", {
        method: "POST",
        body: JSON.stringify({
          region_code: region,
          developers: devs
            ? devs
                .split(",")
                .map((s) => s.trim())
                .filter(Boolean)
            : null,
        }),
      }),
    onSuccess: (data) => {
      console.log("[scrape] lock released:", data);
      queryClient.invalidateQueries({ queryKey: ["scrape-queue"] });
    },
    onError: (err) => {
      console.error("[scrape] release-lock failed:", err);
      alert(`Не удалось снять lock: ${String(err)}`);
    },
  });

  const queue = useQuery({
    queryKey: ["scrape-queue"],
    queryFn: () => apiFetch<QueueStatus>("/api/v1/admin/scrape/queue"),
    refetchInterval: 3000,
  });

  const revokeMutation = useMutation({
    mutationFn: ({
      task_id,
      terminate,
    }: {
      task_id: string;
      terminate: boolean;
    }) =>
      apiFetch<{ revoked: boolean; terminate: boolean }>(
        "/api/v1/admin/scrape/revoke",
        {
          method: "POST",
          body: JSON.stringify({ task_id, terminate }),
        },
      ),
    onSuccess: (data) => {
      console.log("[scrape] revoked:", data);
      queryClient.invalidateQueries({ queryKey: ["scrape-queue"] });
      queryClient.invalidateQueries({ queryKey: ["scrape-runs"] });
    },
    onError: (err) => {
      console.error("[scrape] revoke failed:", err);
      alert(`Не удалось отменить: ${String(err)}`);
    },
  });

  const cancelActive = (taskId: string) => {
    if (
      !confirm(
        "Прервать выполняющийся таск (SIGTERM)? Скрапер остановится мгновенно.",
      )
    ) {
      return;
    }
    revokeMutation.mutate({ task_id: taskId, terminate: true });
  };

  const cancelReserved = (taskId: string) => {
    revokeMutation.mutate({ task_id: taskId, terminate: false });
  };

  const logs = useQuery({
    queryKey: ["scrape-logs", logsRunId],
    queryFn: () => {
      const q =
        logsRunId !== "" ? `?run_id=${logsRunId}&limit=200` : "?limit=200";
      return apiFetch<LogRow[]>(`/api/v1/admin/scrape/logs${q}`);
    },
    refetchInterval: 3000,
  });

  const failures = useQuery({
    queryKey: ["scrape-failures", failuresRunId],
    queryFn: () => {
      const q =
        failuresRunId !== ""
          ? `?run_id=${failuresRunId}&limit=100`
          : "?limit=100";
      return apiFetch<FailureRow[]>(`/api/v1/admin/scrape/failures${q}`);
    },
    enabled: showFailures,
    refetchInterval: showFailures ? 5000 : false,
  });

  const copyUrl = (url: string) => {
    if (typeof navigator !== "undefined" && navigator.clipboard) {
      navigator.clipboard.writeText(url);
    }
  };

  return (
    <>
      <h2 style={{ marginTop: 0, fontSize: 18 }}>
        Скрапер наш.дом.рф — ручной запуск
      </h2>
      <p style={{ color: "#5b6066", fontSize: 13, marginTop: 4 }}>
        Запуск sweep-а вне расписания (расписание: см. SCRAPE_KN_CRON env, по
        умолчанию пн 04:15 МСК с jitter 0–30мин).
      </p>

      <section style={cardStyle}>
        <div style={{ display: "flex", gap: 16, flexWrap: "wrap" }}>
          <label>
            <span style={labelStyle}>Регион</span>
            <input
              type="number"
              value={region}
              min={1}
              max={99}
              onChange={(e) => setRegion(Number(e.target.value))}
              style={{ ...inputStyle, width: 100 }}
            />
          </label>
          <label style={{ flex: 1 }}>
            <span style={labelStyle}>Девелоперы (csv, опц.)</span>
            <input
              value={devs}
              onChange={(e) => setDevs(e.target.value)}
              placeholder="6208_0,5791_0"
              style={inputStyle}
            />
          </label>
          <label
            style={{
              display: "flex",
              alignItems: "center",
              gap: 6,
              marginTop: 22,
            }}
          >
            <input
              type="checkbox"
              checked={fetchFlats}
              onChange={(e) => setFetchFlats(e.target.checked)}
            />
            <span>Квартиры</span>
          </label>
          <label
            style={{
              display: "flex",
              alignItems: "center",
              gap: 6,
              marginTop: 22,
            }}
          >
            <input
              type="checkbox"
              checked={extras}
              onChange={(e) => setExtras(e.target.checked)}
            />
            <span>Extras (sale_graph + agg + infra + photos)</span>
          </label>
          <label
            style={{
              display: "flex",
              alignItems: "center",
              gap: 6,
              marginTop: 22,
            }}
          >
            <input
              type="checkbox"
              checked={downloadPhotos}
              onChange={(e) => setDownloadPhotos(e.target.checked)}
              disabled={!extras}
            />
            <span>Скачать фото (binary)</span>
          </label>
          <label
            style={{
              display: "flex",
              alignItems: "center",
              gap: 6,
              marginTop: 22,
            }}
            title="Перед запуском удалить existing Redis-lock (на случай зомби-worker'а)"
          >
            <input
              type="checkbox"
              checked={forceRun}
              onChange={(e) => setForceRun(e.target.checked)}
            />
            <span style={{ color: forceRun ? "#b3261e" : "inherit" }}>
              ⚡ Force (снять lock)
            </span>
          </label>
        </div>
        <div
          style={{ marginTop: 16, display: "flex", gap: 12, flexWrap: "wrap" }}
        >
          <button
            onClick={() => trigger.mutate()}
            disabled={trigger.isPending}
            style={primaryBtn}
          >
            {trigger.isPending ? "Запускаю…" : "Запустить сейчас"}
          </button>
          <button
            onClick={() => {
              if (
                confirm(
                  "Снять Redis-lock для этого региона/devs? Используй когда подозреваешь зомби-worker.",
                )
              ) {
                releaseLock.mutate();
              }
            }}
            disabled={releaseLock.isPending}
            style={secondaryBtn}
          >
            {releaseLock.isPending ? "Снимаю…" : "🔓 Снять Redis-lock"}
          </button>
        </div>
        {releaseLock.isSuccess ? (
          <div
            style={{
              marginTop: 8,
              padding: 8,
              background: releaseLock.data.released ? "#f0fdf4" : "#f6f7f9",
              border: "1px solid",
              borderColor: releaseLock.data.released ? "#bbf7d0" : "#e6e8ec",
              borderRadius: 6,
              fontSize: 12,
              color: releaseLock.data.released ? "#065f46" : "#5b6066",
            }}
          >
            {releaseLock.data.released
              ? `✓ Lock снят для region=${releaseLock.data.region_code} devs=${releaseLock.data.developers ?? "*"}. Можно запускать.`
              : `Lock не был активен (region=${releaseLock.data.region_code}) — путь чист.`}
          </div>
        ) : null}

        {trigger.isError ? (
          <div
            style={{
              marginTop: 12,
              padding: 12,
              background: "#fef2f2",
              border: "1px solid #fecaca",
              borderRadius: 6,
              color: "#991b1b",
              fontSize: 14,
              wordBreak: "break-word",
            }}
          >
            <strong>Ошибка:</strong> {String(trigger.error)}
            <div style={{ marginTop: 6, fontSize: 12, color: "#7f1d1d" }}>
              Подробности в консоли браузера (F12 → Console).
            </div>
          </div>
        ) : null}

        {trigger.isSuccess ? (
          <div
            style={{
              marginTop: 12,
              padding: 12,
              background: "#f0fdf4",
              border: "1px solid #bbf7d0",
              borderRadius: 6,
              color: "#065f46",
              fontSize: 14,
            }}
          >
            <strong>✓ Поставлено в очередь.</strong> task_id={" "}
            <code
              style={{
                background: "#dcfce7",
                padding: "2px 6px",
                borderRadius: 3,
              }}
            >
              {trigger.data.task_id}
            </code>{" "}
            · регион {trigger.data.region_code}
            <div style={{ marginTop: 6, fontSize: 12, color: "#047857" }}>
              Прогон появится в журнале «Последние прогоны» ниже когда worker
              подхватит задачу.
            </div>
          </div>
        ) : null}
      </section>

      <section style={{ ...cardStyle, marginTop: 16 }}>
        <div
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "space-between",
            marginBottom: 12,
          }}
        >
          <h2 style={{ margin: 0, fontSize: 16 }}>
            Очередь и активные{" "}
            {queue.data ? (
              <span style={{ fontWeight: 400, color: "#5b6066", fontSize: 13 }}>
                · workers: {queue.data.workers.length || "0"} · в очереди:{" "}
                {queue.data.queue_depth ?? "?"} · активно:{" "}
                {queue.data.active.length} · reserved:{" "}
                {queue.data.reserved.length}
              </span>
            ) : null}
          </h2>
        </div>
        {queue.isLoading ? (
          <p style={{ color: "#5b6066" }}>Загрузка…</p>
        ) : queue.isError ? (
          <p style={{ color: "#b3261e" }}>Ошибка: {String(queue.error)}</p>
        ) : queue.data &&
          queue.data.workers.length === 0 &&
          (queue.data.queue_depth ?? 0) === 0 ? (
          <p style={{ color: "#5b6066", fontSize: 13 }}>
            Нет активных worker-ов и очередь пуста. Запусти{" "}
            <code
              style={{
                background: "#f3f4f6",
                padding: "1px 5px",
                borderRadius: 3,
              }}
            >
              docker compose up -d worker beat
            </code>{" "}
            если ожидаешь scheduled-прогон.
          </p>
        ) : queue.data ? (
          <>
            {queue.data.active.length === 0 &&
            queue.data.reserved.length === 0 &&
            queue.data.scheduled.length === 0 ? (
              <div
                style={{
                  padding: 12,
                  background: "#f0fdf4",
                  border: "1px solid #bbf7d0",
                  borderRadius: 6,
                  color: "#065f46",
                  fontSize: 13,
                }}
              >
                ✅ Worker онлайн ({queue.data.workers.join(", ")}) и ждёт задач.
                Активных нет, очередь пуста. Нажми «Запустить сейчас» выше или
                подожди расписание (cron <code>SCRAPE_KN_CRON</code>).
              </div>
            ) : null}
            {queue.data.active.length > 0 ? (
              <>
                <h3
                  style={{
                    fontSize: 14,
                    margin: "8px 0 6px",
                    color: "#0a7a3a",
                  }}
                >
                  ▶ Активные ({queue.data.active.length})
                </h3>
                <table style={queueTable}>
                  <thead>
                    <tr style={{ background: "#f0fdf4" }}>
                      {["Task", "Worker", "Аргументы", "Старт", "Действие"].map(
                        (h) => (
                          <th key={h} style={th}>
                            {h}
                          </th>
                        ),
                      )}
                    </tr>
                  </thead>
                  <tbody>
                    {queue.data.active.map((t) => (
                      <tr
                        key={t.task_id}
                        style={{ borderBottom: "1px solid #eef0f3" }}
                      >
                        <td style={td}>
                          <div style={{ fontWeight: 600 }}>
                            {t.name?.split(".").pop() ?? "—"}
                          </div>
                          <div
                            style={{
                              fontFamily: "monospace",
                              fontSize: 11,
                              color: "#73767e",
                            }}
                          >
                            {t.task_id?.slice(0, 8)}…
                          </div>
                        </td>
                        <td style={td}>{t.worker}</td>
                        <td
                          style={{
                            ...td,
                            fontFamily: "monospace",
                            fontSize: 11,
                          }}
                        >
                          {JSON.stringify(t.args)}{" "}
                          {JSON.stringify(t.kwargs).slice(0, 80)}
                        </td>
                        <td style={td}>
                          {t.time_start
                            ? new Date(t.time_start * 1000).toLocaleTimeString(
                                "ru",
                              )
                            : "—"}
                        </td>
                        <td style={td}>
                          <button
                            onClick={() => cancelActive(t.task_id)}
                            disabled={revokeMutation.isPending}
                            style={dangerBtn}
                            title="SIGTERM прерывает запущенный скрейп мгновенно"
                          >
                            🛑 Прервать
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </>
            ) : null}
            {queue.data.reserved.length > 0 ? (
              <>
                <h3
                  style={{
                    fontSize: 14,
                    margin: "12px 0 6px",
                    color: "#9a6700",
                  }}
                >
                  ⏸ Reserved (приняты worker-ом, не стартовали) (
                  {queue.data.reserved.length})
                </h3>
                <table style={queueTable}>
                  <thead>
                    <tr style={{ background: "#fffbeb" }}>
                      {["Task", "Worker", "Аргументы", "Действие"].map((h) => (
                        <th key={h} style={th}>
                          {h}
                        </th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {queue.data.reserved.map((t) => (
                      <tr
                        key={t.task_id}
                        style={{ borderBottom: "1px solid #eef0f3" }}
                      >
                        <td style={td}>
                          <div style={{ fontWeight: 600 }}>
                            {t.name?.split(".").pop() ?? "—"}
                          </div>
                          <div
                            style={{
                              fontFamily: "monospace",
                              fontSize: 11,
                              color: "#73767e",
                            }}
                          >
                            {t.task_id?.slice(0, 8)}…
                          </div>
                        </td>
                        <td style={td}>{t.worker}</td>
                        <td
                          style={{
                            ...td,
                            fontFamily: "monospace",
                            fontSize: 11,
                          }}
                        >
                          {JSON.stringify(t.args)}{" "}
                          {JSON.stringify(t.kwargs).slice(0, 80)}
                        </td>
                        <td style={td}>
                          <button
                            onClick={() => cancelReserved(t.task_id)}
                            disabled={revokeMutation.isPending}
                            style={dangerBtn}
                            title="Удалить из очереди — worker не запустит этот таск"
                          >
                            ⊘ Удалить из очереди
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </>
            ) : null}
            {queue.data.scheduled.length > 0 ? (
              <>
                <h3
                  style={{
                    fontSize: 14,
                    margin: "12px 0 6px",
                    color: "#5b6066",
                  }}
                >
                  📅 Scheduled (с ETA) ({queue.data.scheduled.length})
                </h3>
                <ul style={{ marginTop: 0, fontSize: 13 }}>
                  {queue.data.scheduled.map((t) => (
                    <li key={t.task_id}>
                      {t.name} → ETA {t.eta} — {JSON.stringify(t.args)}
                    </li>
                  ))}
                </ul>
              </>
            ) : null}
          </>
        ) : null}
      </section>

      <section style={{ ...cardStyle, marginTop: 16 }}>
        <div
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "space-between",
            marginBottom: 12,
          }}
        >
          <h2 style={{ margin: 0, fontSize: 16 }}>
            Прогресс задач{" "}
            <span style={{ fontWeight: 400, color: "#5b6066", fontSize: 13 }}>
              · обновляется каждые 3 сек
            </span>
          </h2>
          <input
            type="number"
            value={logsRunId}
            onChange={(e) =>
              setLogsRunId(e.target.value === "" ? "" : Number(e.target.value))
            }
            placeholder="run_id (опц.)"
            style={{ ...inputStyle, width: 130 }}
          />
        </div>
        {logs.isLoading ? (
          <p style={{ color: "#5b6066" }}>Загрузка…</p>
        ) : logs.isError ? (
          <p style={{ color: "#b3261e" }}>Ошибка: {String(logs.error)}</p>
        ) : (logs.data?.length ?? 0) === 0 ? (
          <p style={{ color: "#5b6066", fontSize: 13 }}>
            Нет событий{logsRunId !== "" ? ` для run_id=${logsRunId}` : ""}.
            Когда worker запустится — появятся записи.
          </p>
        ) : (
          <div
            style={{
              maxHeight: 360,
              overflowY: "auto",
              fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
              fontSize: 12,
              border: "1px solid #eef0f3",
              borderRadius: 6,
              background: "#0f172a",
              color: "#e2e8f0",
              padding: 10,
            }}
          >
            {(logs.data ?? []).map((l) => {
              const color =
                l.level === "error"
                  ? "#fca5a5"
                  : l.level === "warn"
                    ? "#fcd34d"
                    : "#a3e635";
              return (
                <div key={l.log_id} style={{ marginBottom: 2 }}>
                  <span style={{ color: "#94a3b8" }}>
                    {l.ts?.slice(11, 19)}
                  </span>{" "}
                  <span style={{ color }}>{l.level.toUpperCase()}</span>{" "}
                  <span style={{ color: "#7dd3fc" }}>
                    [run-{l.run_id}
                    {l.stage ? ` · ${l.stage}` : ""}
                    {l.obj_id ? ` · obj=${l.obj_id}` : ""}]
                  </span>{" "}
                  <span>{l.message}</span>
                </div>
              );
            })}
          </div>
        )}
      </section>

      <section style={{ ...cardStyle, marginTop: 16 }}>
        <div
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "space-between",
          }}
        >
          <h2 style={{ margin: 0, fontSize: 16 }}>
            Журнал ошибок (per-request)
          </h2>
          <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
            <input
              type="number"
              value={failuresRunId}
              onChange={(e) =>
                setFailuresRunId(
                  e.target.value === "" ? "" : Number(e.target.value),
                )
              }
              placeholder="run_id (опц.)"
              style={{ ...inputStyle, width: 130 }}
            />
            <button
              onClick={() => setShowFailures((v) => !v)}
              style={secondaryBtn}
            >
              {showFailures ? "Скрыть" : "Показать"}
            </button>
          </div>
        </div>
        {showFailures ? (
          failures.isLoading ? (
            <p style={{ color: "#5b6066" }}>Загрузка…</p>
          ) : failures.isError ? (
            <p style={{ color: "#b3261e" }}>Ошибка: {String(failures.error)}</p>
          ) : (failures.data?.length ?? 0) === 0 ? (
            <p style={{ color: "#5b6066" }}>Ошибок нет.</p>
          ) : (
            <table
              style={{
                width: "100%",
                borderCollapse: "collapse",
                fontSize: 12,
                marginTop: 12,
              }}
            >
              <thead>
                <tr style={{ background: "#fef2f2" }}>
                  {[
                    "Когда",
                    "Run",
                    "obj",
                    "endpoint",
                    "Status",
                    "URL",
                    "Body",
                  ].map((h) => (
                    <th key={h} style={th}>
                      {h}
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {(failures.data ?? []).map((f) => (
                  <tr
                    key={f.failure_id}
                    style={{ borderBottom: "1px solid #eef0f3" }}
                  >
                    <td style={td}>
                      {f.occurred_at?.slice(0, 19).replace("T", " ")}
                    </td>
                    <td style={td}>{f.run_id ?? "—"}</td>
                    <td style={td}>{f.obj_id ?? "—"}</td>
                    <td style={td}>{f.endpoint ?? "—"}</td>
                    <td style={{ ...td, color: "#b3261e" }}>
                      {f.http_status ?? "—"}
                    </td>
                    <td
                      style={{ ...td, maxWidth: 380, fontFamily: "monospace" }}
                    >
                      {f.full_url ? (
                        <button
                          onClick={() => copyUrl(f.full_url!)}
                          title="Копировать URL для проверки в браузере"
                          style={{
                            ...secondaryBtn,
                            padding: "2px 8px",
                            fontSize: 11,
                            cursor: "copy",
                          }}
                        >
                          📋 {f.full_url.slice(0, 60)}…
                        </button>
                      ) : (
                        "—"
                      )}
                    </td>
                    <td
                      style={{
                        ...td,
                        fontFamily: "monospace",
                        fontSize: 11,
                        color: "#5b6066",
                        maxWidth: 240,
                      }}
                    >
                      {f.body_preview?.slice(0, 80) ??
                        f.error?.slice(0, 80) ??
                        ""}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          )
        ) : null}
      </section>

      <section style={{ ...cardStyle, marginTop: 16 }}>
        <h2 style={{ marginTop: 0, fontSize: 16 }}>Последние прогоны</h2>
        {runs.isLoading ? (
          <p>Загрузка…</p>
        ) : runs.isError ? (
          <p style={{ color: "#b3261e" }}>Ошибка: {String(runs.error)}</p>
        ) : (
          <table
            style={{ width: "100%", borderCollapse: "collapse", fontSize: 13 }}
          >
            <thead>
              <tr style={{ background: "#f6f7f9" }}>
                {[
                  "#",
                  "Старт",
                  "Регион",
                  "Dev",
                  "Status",
                  "Объектов",
                  "Квартир",
                  "Req",
                  "Ошибка",
                ].map((h) => (
                  <th key={h} style={th}>
                    {h}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {(runs.data ?? []).map((r) => (
                <tr
                  key={r.run_id}
                  style={{ borderBottom: "1px solid #eef0f3" }}
                >
                  <td style={td}>{r.run_id}</td>
                  <td style={td}>
                    {r.started_at?.slice(0, 19).replace("T", " ")}
                  </td>
                  <td style={td}>{r.region_codes.join(",")}</td>
                  <td style={td}>{r.developer_ids?.join(",") || "—"}</td>
                  <td
                    style={{
                      ...td,
                      color:
                        r.status === "done"
                          ? "#0a7a3a"
                          : r.status === "failed"
                            ? "#b3261e"
                            : "#9a6700",
                      fontWeight: 600,
                    }}
                  >
                    {r.status}
                  </td>
                  <td style={td}>{r.objects_count ?? "—"}</td>
                  <td style={td}>{r.flats_count ?? "—"}</td>
                  <td style={td}>{r.requests_count ?? "—"}</td>
                  <td
                    style={{
                      ...td,
                      color: "#b3261e",
                      maxWidth: 240,
                      overflow: "hidden",
                      textOverflow: "ellipsis",
                      whiteSpace: "nowrap",
                    }}
                  >
                    {r.error ?? ""}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </section>
    </>
  );
}

const primaryBtn = {
  padding: "10px 18px",
  background: "#1d4ed8",
  color: "#fff",
  border: "none",
  borderRadius: 6,
  fontSize: 14,
  fontWeight: 600,
  cursor: "pointer",
};
const secondaryBtn = {
  padding: "8px 14px",
  background: "#f3f4f6",
  color: "#1f2937",
  border: "1px solid #d1d5db",
  borderRadius: 6,
  fontSize: 13,
  cursor: "pointer",
};
const dangerBtn = {
  padding: "4px 10px",
  background: "#fef2f2",
  color: "#991b1b",
  border: "1px solid #fecaca",
  borderRadius: 4,
  fontSize: 12,
  cursor: "pointer",
};
const queueTable = {
  width: "100%",
  borderCollapse: "collapse" as const,
  fontSize: 13,
  marginBottom: 4,
};
