import { db, featureFlags, users, eq, and } from "@epicure/db";

export type Tier = "free" | "pro" | "family";
export const TIERS: Tier[] = ["free", "pro", "family"];

export const FEATURE_DEFINITIONS = [
  {
    key: "recipe_variations",
    label: "Recipe variations",
    description: "AI-generated variations of a recipe (dietary swaps, flavor twists, etc.).",
  },
  {
    key: "drink_pairing",
    label: "Drink pairing",
    description: "AI-suggested drink pairings for a recipe.",
  },
  {
    key: "meal_pairing",
    label: "Meal pairing",
    description: "AI-suggested side dish / meal pairings for a recipe.",
  },
] as const;

export type FeatureKey = (typeof FEATURE_DEFINITIONS)[number]["key"];
export const FEATURE_KEYS = FEATURE_DEFINITIONS.map((f) => f.key) as FeatureKey[];

export class FeatureDisabledError extends Error {
  constructor(public readonly featureKey: FeatureKey) {
    super(`Feature disabled for your tier: ${featureKey}`);
    this.name = "FeatureDisabledError";
  }
}

/** Full (feature x tier) matrix, defaulting every cell to enabled=true unless
 *  a row overrides it. Used by the admin toggle UI. */
export async function getFeatureFlagMatrix(): Promise<Record<FeatureKey, Record<Tier, boolean>>> {
  const rows = await db.select().from(featureFlags);
  const overrides = new Map(rows.map((r) => [`${r.featureKey}:${r.tier}`, r.enabled]));

  const matrix = {} as Record<FeatureKey, Record<Tier, boolean>>;
  for (const key of FEATURE_KEYS) {
    matrix[key] = {} as Record<Tier, boolean>;
    for (const tier of TIERS) {
      matrix[key][tier] = overrides.get(`${key}:${tier}`) ?? true;
    }
  }
  return matrix;
}

export async function setFeatureFlag(
  featureKey: FeatureKey,
  tier: Tier,
  enabled: boolean,
  updatedById: string
): Promise<void> {
  await db
    .insert(featureFlags)
    .values({ featureKey, tier, enabled, updatedAt: new Date(), updatedById })
    .onConflictDoUpdate({
      target: [featureFlags.featureKey, featureFlags.tier],
      set: { enabled, updatedAt: new Date(), updatedById },
    });
}

export async function isFeatureEnabledForTier(featureKey: FeatureKey, tier: Tier): Promise<boolean> {
  const [row] = await db
    .select({ enabled: featureFlags.enabled })
    .from(featureFlags)
    .where(and(eq(featureFlags.featureKey, featureKey), eq(featureFlags.tier, tier)));
  return row ? row.enabled : true;
}

/**
 * Server-side enforcement for API routes — never trust the session's tier
 * (5-minute cookieCache, see lib/auth/server.ts), re-read it from the DB,
 * same rationale as checkAndIncrementTierLimit.
 */
export async function requireFeatureEnabled(userId: string, featureKey: FeatureKey): Promise<void> {
  const [dbUser] = await db.select({ tier: users.tier }).from(users).where(eq(users.id, userId));
  const tier = (dbUser?.tier ?? "free") as Tier;
  const enabled = await isFeatureEnabledForTier(featureKey, tier);
  if (!enabled) throw new FeatureDisabledError(featureKey);
}
