// Per-user, per-AI-kind rate limit. Backed by ai_request_log; rolling 60s window.
// Best-effort (not atomic) — sufficient for normal abuse prevention on a small backend.
// For high-concurrency hard limits, swap for a Redis/Cloudflare KV counter later.
import type { SupabaseClient } from "@supabase/supabase-js";
import { logAiRequest, type AiRequestKind } from "./ai-monitoring.server";

export type Plan = "free" | "pro" | "agency" | "enterprise";

// requests per 60 seconds, per AI kind
export const RATE_LIMITS: Record<Plan, number> = {
  free: 10,
  pro: 30,
  agency: 60,
  enterprise: 240, // bump per-customer later
};

export class RateLimitError extends Error {
  constructor(public plan: Plan, public limit: number, public kind: AiRequestKind) {
    super(
      `You've reached the ${plan} plan limit of ${limit} ${kind.replace("_", " ")} requests per minute. Please wait a moment and try again.`,
    );
    this.name = "RateLimitError";
  }
}

export async function enforceRateLimit(
  supabase: SupabaseClient,
  userId: string,
  kind: AiRequestKind,
): Promise<void> {
  // Resolve plan via SECURITY DEFINER RPC so a missing subscription row is fine.
  const { data: planData } = await supabase.rpc("current_user_plan");
  const plan = ((planData as string | null) ?? "free") as Plan;
  const limit = RATE_LIMITS[plan] ?? RATE_LIMITS.free;

  const { data: count, error } = await supabase.rpc("ai_recent_request_count", {
    _kind: kind,
    _window_seconds: 60,
  });
  if (error) {
    // If the count check fails, fail open rather than blocking real users.
    console.error("[rate-limit] count rpc failed, allowing request:", error.message);
    return;
  }
  const used = (count as number | null) ?? 0;
  if (used >= limit) {
    await logAiRequest({ userId, kind, status: "rate_limited", errorCode: `plan:${plan}` });
    throw new RateLimitError(plan, limit, kind);
  }
}
