import React, { createContext, useContext, useMemo } from 'react';
import { resolveTheme, type ShadeTheme, type ThemeMode } from './theme.js';

export interface ShadeContextValue {
  observerUrl: string;
  token: string;
  theme: ShadeTheme;
  pollIntervalMs: number;
}

const ShadeContext = createContext<ShadeContextValue | null>(null);

export interface ShadeProviderProps {
  /** Base URL of the Shade observer endpoint, e.g. "https://shade.example.com/shade-observer" */
  observerUrl: string;
  /** Bearer token for the observer (matches SHADE_OBSERVER_TOKEN on the server) */
  token: string;
  /** Theme mode: dark, light, or auto (matches system preference). Default: dark. */
  themeMode?: ThemeMode;
  /** How often to poll /api/state in milliseconds. Default: 5000. */
  pollIntervalMs?: number;
  children: React.ReactNode;
}

/**
 * ShadeProvider — root context provider that all Shade widgets need.
 *
 * Wrap your dashboard or specific widget container with this and pass
 * the observer URL + token. All child widgets will share the connection.
 *
 * ```tsx
 * <ShadeProvider observerUrl="https://x.com/shade-observer" token={process.env.TOKEN!}>
 *   <SessionList />
 *   <PrekeyStock />
 * </ShadeProvider>
 * ```
 */
export function ShadeProvider({
  observerUrl,
  token,
  themeMode = 'dark',
  pollIntervalMs = 5000,
  children,
}: ShadeProviderProps): React.ReactElement {
  const value = useMemo<ShadeContextValue>(
    () => ({
      observerUrl: observerUrl.replace(/\/$/, ''),
      token,
      theme: resolveTheme(themeMode),
      pollIntervalMs,
    }),
    [observerUrl, token, themeMode, pollIntervalMs],
  );

  return <ShadeContext.Provider value={value}>{children}</ShadeContext.Provider>;
}

/** Internal hook used by widgets to access the context. Throws if no provider. */
export function useShadeContext(): ShadeContextValue {
  const ctx = useContext(ShadeContext);
  if (!ctx) {
    throw new Error(
      'Shade widgets must be wrapped in <ShadeProvider observerUrl="..." token="..." />',
    );
  }
  return ctx;
}
