import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useTranslation } from "react-i18next";
import { CheckCircle2, Clock, Database, History, Loader2, Pause, Play } from "lucide-react";
import { api, type MyStatus } from "../lib/api";
import { formatViews } from "../lib/format";
import Tooltip from "./Tooltip";

// Per-user status (not the global catalog): shows the number of videos available to *this*
// user, how many of *their* channels are still being fetched, and how many lack full
// history (clickable -> channel manager filtered to those). The pause control is admin-only.
export default function SyncStatus({
  isAdmin,
  onGoToFullHistory,
  variant = "bar",
  collapsed = false,
}: {
  isAdmin: boolean;
  onGoToFullHistory: () => void;
  // "bar" = the legacy horizontal top-bar row. "rail" = a compact block for the top of the
  // left nav sidebar (stacked; icon-only with a tooltip when the rail is collapsed).
  variant?: "bar" | "rail";
  collapsed?: boolean;
}) {
  const { t } = useTranslation();
  const qc = useQueryClient();
  const { data } = useQuery({
    queryKey: ["my-status"],
    queryFn: api.myStatus,
    // Track the scheduler near-real-time: poll even when the tab is backgrounded, and
    // refresh immediately on tab focus (the global default disables focus refetch), so the
    // "N without full history" count keeps ticking down without a manual reload. Poll faster
    // while a job is running or work is pending — so the live "syncing" state is actually
    // caught — and ease back to a slow idle tick once everything's settled.
    refetchInterval: (query) => {
      const d = query.state.data as MyStatus | undefined;
      const busy =
        !!d &&
        (d.sync_active || d.channels_recent_pending > 0 || d.channels_deep_pending > 0);
      return busy ? 8_000 : 30_000;
    },
    refetchIntervalInBackground: true,
    refetchOnWindowFocus: true,
    staleTime: 5_000,
  });

  const toggle = useMutation({
    mutationFn: () => (data?.paused ? api.resumeSync() : api.pauseSync()),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["my-status"] }),
  });

  if (!data) return null;

  const syncing = data.channels_recent_pending;
  const notFull = data.channels_deep_pending; // your channels without full history yet
  // Spin only while a sync job is actually running; otherwise pending work shows as a calm,
  // static state (or, for deep history, just the "N without full history" link below).
  const active = data.sync_active;
  const showMain = data.paused || active || syncing > 0 || notFull === 0;

  // Calm one-liner describing the current sync state; shared by the bar and rail layouts.
  const stateNode = data.paused ? (
    <span className="text-accent font-medium">{t("header.sync.paused")}</span>
  ) : active ? (
    <span className="flex items-center gap-1">
      <Loader2 className="w-3.5 h-3.5 animate-spin" />
      {syncing > 0
        ? t("header.sync.syncing", { count: syncing })
        : notFull > 0
          ? t("header.sync.backfillingHistory")
          : t("header.sync.working")}
    </span>
  ) : syncing > 0 ? (
    <span className="flex items-center gap-1">
      <Clock className="w-3.5 h-3.5" />
      {t("header.sync.recentQueued", { count: syncing })}
    </span>
  ) : (
    // A small check anchors the "all synced" state so it doesn't read as orphaned text.
    <span className="flex items-center gap-1 text-emerald-500">
      <CheckCircle2 className="w-3.5 h-3.5" />
      <span className="text-muted">{t("header.sync.allSynced")}</span>
    </span>
  );

  const pauseBtn = isAdmin && (data.paused || syncing > 0 || notFull > 0) && (
    <button
      onClick={() => toggle.mutate()}
      disabled={toggle.isPending}
      title={data.paused ? t("header.sync.resume") : t("header.sync.pause")}
      className="p-1 rounded-md hover:bg-card hover:text-fg transition"
    >
      {data.paused ? <Play className="w-3.5 h-3.5" /> : <Pause className="w-3.5 h-3.5" />}
    </button>
  );

  // Rail: a compact block at the top of the left nav. Collapsed → a single icon (spinner while
  // syncing) with the counts in a tooltip; a small accent dot flags paused / missing-history.
  if (variant === "rail") {
    const countsText = `${formatViews(data.my_videos)} ${t("header.sync.yours")} / ${formatViews(
      data.total_videos
    )} ${t("header.sync.total")}`;
    if (collapsed) {
      return (
        <Tooltip hint={countsText}>
          <div className="relative grid place-items-center py-1 text-muted">
            {active ? (
              <Loader2 className="w-4 h-4 animate-spin" />
            ) : (
              <Database className="w-4 h-4" />
            )}
            {(data.paused || notFull > 0) && (
              <span className="absolute top-0 right-1 w-2 h-2 rounded-full bg-accent ring-2 ring-bg" />
            )}
          </div>
        </Tooltip>
      );
    }
    return (
      <div className="text-[11px] text-muted leading-snug space-y-1">
        <Tooltip hint={t("header.sync.countTooltip")}>
          <span className="flex items-center gap-1.5 cursor-default">
            <Database className="w-3.5 h-3.5 shrink-0" />
            <span className="truncate">
              <span className="text-fg font-medium">{formatViews(data.my_videos)}</span>{" "}
              {t("header.sync.yours")}
              <span className="opacity-40"> / </span>
              {formatViews(data.total_videos)} {t("header.sync.total")}
            </span>
          </span>
        </Tooltip>
        {/* Pause sits inline at the right end of the primary status row (the sync state, or —
            when idle with only deep-history pending — the "N without full history" row), never on
            an orphaned line of its own. */}
        {showMain && (
          <div className="flex items-center justify-between gap-1.5">
            <span className="flex items-center gap-1.5 min-w-0">{stateNode}</span>
            {pauseBtn}
          </div>
        )}
        {notFull > 0 && (
          <div className="flex items-center justify-between gap-1.5">
            <Tooltip hint={t("header.sync.fullHistoryTooltip")}>
              <button
                onClick={onGoToFullHistory}
                className="flex items-center gap-1 hover:text-fg underline decoration-dotted decoration-muted/40 underline-offset-4 transition cursor-pointer"
              >
                <History className="w-3.5 h-3.5" />
                {t("header.sync.withoutFullHistory", { count: notFull })}
              </button>
            </Tooltip>
            {!showMain && pauseBtn}
          </div>
        )}
      </div>
    );
  }

  return (
    <div className="hidden lg:flex items-center gap-2 text-xs text-muted">
      <Tooltip hint={t("header.sync.countTooltip")}>
        <span className="flex items-center gap-1.5 cursor-default">
          <Database className="w-3.5 h-3.5" />
          <span>
            <span className="text-fg font-medium">{formatViews(data.my_videos)}</span>{" "}
            {t("header.sync.yours")}
          </span>
          <span className="opacity-40">/</span>
          <span>
            {formatViews(data.total_videos)} {t("header.sync.total")}
          </span>
        </span>
      </Tooltip>
      {showMain && (
        <>
          <span className="opacity-40">·</span>
          {data.paused ? (
            <span className="text-accent font-medium">{t("header.sync.paused")}</span>
          ) : active ? (
            // A sync job is running right now — spin and name what it's doing.
            <span className="flex items-center gap-1">
              <Loader2 className="w-3.5 h-3.5 animate-spin" />
              {syncing > 0
                ? t("header.sync.syncing", { count: syncing })
                : notFull > 0
                  ? t("header.sync.backfillingHistory")
                  : t("header.sync.working")}
            </span>
          ) : syncing > 0 ? (
            // Recent uploads queued for the next run, but nothing running now — static.
            <span className="flex items-center gap-1">
              <Clock className="w-3.5 h-3.5" />
              {t("header.sync.recentQueued", { count: syncing })}
            </span>
          ) : (
            <span>{t("header.sync.allSynced")}</span>
          )}
        </>
      )}
      {notFull > 0 && (
        <>
          <span className="opacity-40">·</span>
          <Tooltip hint={t("header.sync.fullHistoryTooltip")}>
            <button
              onClick={onGoToFullHistory}
              className="flex items-center gap-1 hover:text-fg underline decoration-dotted decoration-muted/40 underline-offset-4 transition cursor-pointer"
            >
              <History className="w-3.5 h-3.5" />
              {t("header.sync.withoutFullHistory", { count: notFull })}
            </button>
          </Tooltip>
        </>
      )}
      {/* Pause only makes sense when there's work to pause (recent OR deep backfill);
          Resume must always show while paused so it can be lifted. Hidden entirely when
          idle and not paused. */}
      {isAdmin && (data.paused || syncing > 0 || notFull > 0) && (
        <button
          onClick={() => toggle.mutate()}
          disabled={toggle.isPending}
          title={data.paused ? t("header.sync.resume") : t("header.sync.pause")}
          className="ml-1 p-1 rounded-md hover:bg-card hover:text-fg transition"
        >
          {data.paused ? <Play className="w-3.5 h-3.5" /> : <Pause className="w-3.5 h-3.5" />}
        </button>
      )}
    </div>
  );
}
