import { useTranslation } from "react-i18next";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { UserPlus } from "lucide-react";
import { api, HttpError, type DiscoveredChannel } from "../lib/api";
import { formatViews } from "../lib/format";
import { notify } from "../lib/notifications";
import Tooltip from "./Tooltip";
import ChannelLink from "./ChannelLink";
import DataTable, { type Column } from "./DataTable";

// The Channel manager's "Discovery" tab: channels that turn up in the user's playlists but
// that they don't subscribe to. Subscribing here only creates the subscription + enriches
// the channel's metadata — the scheduler pulls its videos on its next run (see backend).
export default function ChannelDiscovery({
  canWrite,
  onOpenWizard,
}: {
  canWrite: boolean;
  onOpenWizard: () => void;
}) {
  const { t } = useTranslation();
  const qc = useQueryClient();

  const query = useQuery({
    queryKey: ["discovered-channels"],
    queryFn: api.discoveredChannels,
  });

  const subscribe = useMutation({
    mutationFn: (c: DiscoveredChannel) => api.subscribeChannel(c.id),
    onSuccess: (_data, c) => {
      // The channel moves from "discovery" to "subscribed", and its videos will start
      // arriving — refresh both lists plus the per-user status.
      qc.invalidateQueries({ queryKey: ["discovered-channels"] });
      qc.invalidateQueries({ queryKey: ["channels"] });
      qc.invalidateQueries({ queryKey: ["my-status"] });
      const name = c.title ?? c.id;
      // Name the channel and ship a typed payload so the inbox can offer "open in the
      // Channel manager" / "open on YouTube" links — kept after reload, when live
      // callbacks are gone (see ChannelSubscribedMeta).
      notify({
        level: "success",
        title: t("channels.discovery.subscribedTitle"),
        message: t("channels.discovery.subscribedBody", { name }),
        meta: { kind: "channel-subscribed", channelId: c.id, channelName: name },
      });
    },
    onError: (err: unknown) => {
      // A 403 means the user hasn't granted the write scope — offer to connect instead of
      // a vague failure (mirrors the subscriptions tab).
      if (err instanceof HttpError && err.status === 403) {
        notify({
          level: "error",
          message: t("channels.notify.needYouTube"),
          action: { label: t("channels.notify.connect"), onClick: onOpenWizard },
        });
      } else {
        notify({ level: "error", message: t("channels.discovery.subscribeFailed") });
      }
    },
  });

  const rows = query.data ?? [];

  const columns: Column<DiscoveredChannel>[] = [
    {
      key: "channel",
      header: t("channels.cols.channel"),
      sortable: true,
      sortValue: (c) => (c.title ?? c.id).toLowerCase(),
      filter: { kind: "text", get: (c) => `${c.title ?? ""} ${c.handle ?? ""}` },
      cardPrimary: true,
      render: (c) => (
        <ChannelLink id={c.id} title={c.title} handle={c.handle} thumbnailUrl={c.thumbnail_url} />
      ),
    },
    {
      key: "subs",
      header: t("channels.cols.subs"),
      align: "right",
      nowrap: true,
      sortable: true,
      sortValue: (c) => c.subscriber_count ?? -1,
      render: (c) => (
        <span className="text-muted tabular-nums">
          {c.subscriber_count != null ? formatViews(c.subscriber_count) : "—"}
        </span>
      ),
    },
    {
      key: "inPlaylists",
      header: t("channels.discovery.cols.inPlaylists"),
      align: "right",
      nowrap: true,
      sortable: true,
      sortValue: (c) => c.playlist_video_count,
      render: (c) => (
        <Tooltip
          hint={t("channels.discovery.cols.inPlaylistsHint", {
            videos: c.playlist_video_count,
            playlists: c.playlist_count,
          })}
        >
          <span className="text-muted tabular-nums cursor-help">
            {c.playlist_video_count} / {c.playlist_count}
          </span>
        </Tooltip>
      ),
    },
    {
      key: "actions",
      header: t("channels.cols.actions"),
      align: "right",
      nowrap: true,
      width: "120px",
      cardLabel: false,
      render: (c) => (
        <Tooltip
          hint={
            canWrite
              ? t("channels.discovery.subscribeHint")
              : t("channels.discovery.needWriteHint")
          }
        >
          <button
            onClick={() => subscribe.mutate(c)}
            disabled={!canWrite || subscribe.isPending}
            className="glass-card glass-hover inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-xs disabled:opacity-50 transition"
          >
            <UserPlus className="w-3.5 h-3.5" />
            {t("channels.discovery.subscribe")}
          </button>
        </Tooltip>
      ),
    },
  ];

  return (
    <div className="px-4 pb-4 pt-3 max-w-7xl mx-auto">
      <p className="text-xs text-muted mb-4 leading-relaxed">
        {t("channels.discovery.intro")}
      </p>
      {query.isLoading ? (
        <div className="text-muted py-8">{t("channels.discovery.loading")}</div>
      ) : (
        <DataTable
          rows={rows}
          columns={columns}
          rowKey={(c) => c.id}
          persistKey="siftlode.channelDiscoveryTable"
          controlsPosition="top"
          emptyText={t("channels.discovery.empty")}
        />
      )}
    </div>
  );
}
