import useSWR, { type SWRResponse, useSWRConfig } from "swr";
import { fetchJson } from "./apiClient";
import {
  DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
  RuntimeConfigSchema,
  type RuntimeConfig,
} from "./runtimeConfig";

export const ONBOARDING_SWR_KEY = "/api/config";

async function fetcher(url: string): Promise<RuntimeConfig> {
  return fetchJson(
    url,
    RuntimeConfigSchema,
    undefined,
    (response) => `Failed to fetch ${url}: ${response.status}`,
  );
}

async function patchRuntimeConfig(patch: Partial<RuntimeConfig>): Promise<RuntimeConfig> {
  return fetchJson(
    ONBOARDING_SWR_KEY,
    RuntimeConfigSchema,
    {
      method: "PATCH",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(patch),
    },
    (response) => `PATCH failed with status ${response.status}`,
  );
}

export type UseOnboarding = {
  hasSeenOnboarding: boolean;
  isLoading: boolean;
  markSeen: () => Promise<void>;
};

/**
 * Hook for the first-launch onboarding banner. The server's
 * `hasSeenOnboarding` flag is the source of truth — set to `true` on
 * dismissal and persisted in the server config file so it survives
 * across browser sessions.
 *
 * `hasSeenOnboarding` defaults to `false` until the SWR fetch resolves,
 * which means the banner shows briefly on first load. That is
 * acceptable: the fetch is local and resolves within milliseconds.
 */
export function useOnboarding(): UseOnboarding {
  const response: SWRResponse<RuntimeConfig, Error> = useSWR<RuntimeConfig, Error>(
    ONBOARDING_SWR_KEY,
    fetcher,
    {
      revalidateOnFocus: false,
      revalidateIfStale: false,
    },
  );
  const { mutate: globalMutate } = useSWRConfig();

  const hasSeenOnboarding = response.data?.hasSeenOnboarding ?? false;

  const markSeen = async (): Promise<void> => {
    await globalMutate(ONBOARDING_SWR_KEY, patchRuntimeConfig({ hasSeenOnboarding: true }), {
      optimisticData: {
        stripClaudeCodeBillingHeader: response.data?.stripClaudeCodeBillingHeader ?? false,
        hasSeenOnboarding: true,
        slowResponseThresholdSeconds:
          response.data?.slowResponseThresholdSeconds ?? DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
      },
      rollbackOnError: true,
      revalidate: false,
    });
  };

  return {
    hasSeenOnboarding,
    isLoading: response.isLoading,
    markSeen,
  };
}
