import "server-only";

import type { ComponentType } from "react";
import { defineLive } from "next-sanity/live";

import { isConfigured, readToken } from "./env";
import { getClient } from "./client";

/**
 * Live Content integration for next-sanity.
 *
 * When Sanity is configured we call `defineLive` from `next-sanity/live`
 * which returns a `<SanityLive />` React component that opens an EventSource
 * to the Sanity Live API and invalidates cached fetches when content
 * changes. Mounted in `src/app/layout.tsx` once, site-wide.
 *
 * When Sanity is NOT configured (no project id), we export a no-op
 * component so `<SanityLive />` in the root layout is always safe to
 * render without throwing. The existing `sanityFetchList` / `sanityFetchOne`
 * wrappers continue to back the fetch path; Live Content is a best-effort
 * realtime layer on top of the static generation we already have.
 *
 * Note: we intentionally do NOT re-export `sanityFetch` here. The existing
 * fetch wrappers in `./fetch` already encode the fallback contract and the
 * preview mode plumbing; switching every call site to `liveSanityFetch`
 * would lose that. The `<SanityLive />` component alone is enough to
 * invalidate cached data on publish.
 */

type LiveComponent = ComponentType<Record<string, unknown>>;

const NoopLive: LiveComponent = () => null;

function buildLive(): LiveComponent {
  if (!isConfigured) return NoopLive;
  try {
    const client = getClient();
    const { SanityLive: Live } = defineLive({
      client,
      serverToken: readToken ?? false,
      browserToken: readToken ?? false,
    });
    return Live as unknown as LiveComponent;
  } catch {
    // defineLive might throw if the runtime cannot support it (e.g. edge).
    return NoopLive;
  }
}

export const SanityLive: LiveComponent = buildLive();
