import type { ReactNode } from 'react';
import { useMemo } from 'react';
import { useDevUser } from '@lilith/ui-dev-tools';
import type { DevUserState } from '@lilith/ui-dev-tools';
import { AuthProvider } from './AuthProvider';
import type { User, DevAuthOverride } from './types';

/**
 * Function to map dev user state to a mock User object.
 * Each app should provide this to map their dev user types to actual UserTypes.
 */
export type DevUserMapper = (devUser: DevUserState) => User;

interface AuthProviderWithDevBridgeProps {
  children: ReactNode;
  /** SSO service URL (required for real auth) */
  ssoUrl: string;
  /**
   * Function to map dev user state to a User object.
   * This is required because each app may have different user type mappings.
   *
   * @example
   * ```tsx
   * const mapDevUser: DevUserMapper = (devUser) => ({
   *   id: devUser.userId || 'dev-user',
   *   email: `${devUser.primaryType}@dev.local`,
   *   username: devUser.displayName,
   *   role: UserRole.USER,
   *   userTypes: devUser.userTypes.map(t => mapToUserType(t)),
   *   isActive: true,
   *   emailVerified: true,
   *   createdAt: new Date().toISOString(),
   *   updatedAt: new Date().toISOString(),
   * });
   * ```
   */
  mapDevUser: DevUserMapper;
}

/**
 * AuthProvider wrapper that bridges DevUserProvider state to AuthProvider.
 *
 * When dev auth is active (import.meta.env.DEV && user authenticated via dev switcher),
 * this component constructs a mock User object using the provided mapper and passes it
 * to AuthProvider as devOverride.
 *
 * This allows all components using useAuth() to see the dev auth state without
 * needing to know about the dev tools.
 *
 * @example
 * ```tsx
 * <DevUserProvider userTypes={DEV_USER_TYPES} storageKey="myapp_dev_user">
 *   <AuthProviderWithDevBridge ssoUrl={config.ssoUrl} mapDevUser={mapDevUser}>
 *     <App />
 *   </AuthProviderWithDevBridge>
 *   <DevUserSwitcher />
 * </DevUserProvider>
 * ```
 */
export function AuthProviderWithDevBridge({
  children,
  ssoUrl,
  mapDevUser,
}: AuthProviderWithDevBridgeProps) {
  const devUser = useDevUser();

  const devOverride = useMemo<DevAuthOverride | undefined>(() => {
    // Only create override when in dev mode AND user is authenticated via dev switcher
    if (!devUser.isDevMode || !devUser.isAuthenticated) {
      return undefined;
    }

    // Use the provided mapper to create the mock user
    const mockUser = mapDevUser(devUser);

    return {
      isAuthenticated: true,
      user: mockUser,
    };
  }, [devUser, mapDevUser]);

  return (
    <AuthProvider ssoUrl={ssoUrl} devOverride={devOverride}>
      {children}
    </AuthProvider>
  );
}
