/**
 * Redis Cache Usage Examples
 *
 * This file demonstrates how to use the Redis cache layer
 * for user profiles, pricing tiers, and settings.
 */

import {
  getUserProfile,
  getUserProfileByEmail,
  invalidateUserProfile,
  getPricingTiers,
  getPricingTier,
  invalidatePricingTiers,
  getSettings,
  getSetting,
  invalidateSettings,
  getCacheHitRate,
} from "./redis-cache";

/**
 * Example 1: Fetch user profile with caching
 */
export async function exampleUserProfile() {
  // First call - cache miss, fetches from database
  const user1 = await getUserProfile("user-123");
  console.log("User profile (cache miss):", user1);

  // Second call - cache hit, returns from Redis
  const user2 = await getUserProfile("user-123");
  console.log("User profile (cache hit):", user2);

  // Fetch by email
  const userByEmail = await getUserProfileByEmail("test@example.com");
  console.log("User by email:", userByEmail);

  // After updating user in database, invalidate cache
  // await prisma.users.update({ where: { id: 'user-123' }, data: { ... } });
  await invalidateUserProfile("user-123", "test@example.com");

  // Next fetch will be a cache miss and get fresh data
  const updatedUser = await getUserProfile("user-123");
  console.log("Updated user (fresh from DB):", updatedUser);
}

/**
 * Example 2: Fetch pricing tiers with caching
 */
export async function examplePricingTiers() {
  // Fetch all tiers - cached for 1 hour
  const allTiers = await getPricingTiers();
  console.log("All pricing tiers:", allTiers);

  // Fetch specific tier
  const professionalTier = await getPricingTier("tier2");
  console.log("Professional tier:", professionalTier);

  // After updating pricing in Stripe, invalidate cache
  await invalidatePricingTiers();

  // Next fetch will get fresh data
  const updatedTiers = await getPricingTiers();
  console.log("Updated tiers:", updatedTiers);
}

/**
 * Example 3: Fetch application settings with caching
 */
export async function exampleSettings() {
  // Fetch all app settings - cached for 15 minutes
  const appSettings = await getSettings("app");
  console.log("App settings:", appSettings);

  // Fetch specific setting
  const maxUploadSize = await getSetting<number>("app", "maxUploadSize");
  console.log("Max upload size:", maxUploadSize);

  // Fetch billing settings
  const billingSettings = await getSettings("billing");
  console.log("Billing settings:", billingSettings);

  // After updating settings, invalidate cache
  await invalidateSettings("app");
  await invalidateSettings("billing");
}

/**
 * Example 4: Monitor cache performance
 */
export async function exampleCacheMonitoring() {
  // Simulate multiple requests
  for (let i = 0; i < 10; i++) {
    await getUserProfile("user-123");
    await getPricingTiers();
    await getSettings("app");
  }

  // Check cache hit rate
  const metrics = getCacheHitRate();
  console.log("Cache metrics:", {
    totalRequests: metrics.total,
    hits: metrics.hits,
    misses: metrics.misses,
    hitRate: metrics.hitRatio
      ? `${(metrics.hitRatio * 100).toFixed(2)}%`
      : "N/A",
  });

  console.log("Namespace metrics:");
  console.log("- User profiles:", metrics.namespaces.userProfile);
  console.log("- Pricing tiers:", metrics.namespaces.pricingTiers);
  console.log("- Settings:", metrics.namespaces.settings);
}

/**
 * Example 5: Integration with API routes
 *
 * app/api/users/[id]/route.ts
 */
export async function exampleAPIRoute() {
  /*
  import { getUserProfile, invalidateUserProfile } from '@/lib/cache/redis-cache';

  // GET /api/users/[id]
  export async function GET(req: Request, { params }: { params: { id: string } }) {
    const user = await getUserProfile(params.id);

    if (!user) {
      return Response.json({ error: 'User not found' }, { status: 404 });
    }

    return Response.json(user);
  }

  // PATCH /api/users/[id]
  export async function PATCH(req: Request, { params }: { params: { id: string } }) {
    const data = await req.json();

    // Update user in database
    const updatedUser = await prisma.users.update({
      where: { id: params.id },
      data,
    });

    // Invalidate cache
    await invalidateUserProfile(params.id, updatedUser.email || undefined);

    return Response.json(updatedUser);
  }
  */
}

/**
 * Example 6: Cache warming strategy
 */
export async function exampleCacheWarming() {
  // Pre-populate cache with frequently accessed data
  const commonUserIds = ["user-1", "user-2", "user-3"];

  await Promise.all([
    // Warm user profiles
    ...commonUserIds.map((id) => getUserProfile(id)),
    // Warm pricing tiers
    getPricingTiers(),
    // Warm common settings
    getSettings("app"),
    getSettings("billing"),
  ]);

  console.log("Cache warmed successfully");
}

/**
 * Example 7: Handling cache failures gracefully
 */
export async function exampleGracefulDegradation() {
  // The cache layer automatically falls back to database on Redis failures
  // No special handling needed - it's transparent to the caller

  try {
    const user = await getUserProfile("user-123");
    // This will work even if Redis is down - it falls back to direct DB query
    console.log("User:", user);
  } catch (error) {
    // Only database errors will throw here, not cache errors
    console.error("Database error:", error);
  }
}
