import { getPool, isPoolHealthy } from "./db.js";
const DEFAULT_PLAN = "free";
const DEFAULT_FLAGS = [];
const isDevelopment = process.env.NODE_ENV !== "production";
const userDataCache = /* @__PURE__ */ new Map();
const CACHE_TTL = 5 * 60 * 1e3;
const MAX_CACHE_SIZE = 1e4;
function evictOldestCacheEntries() {
  if (userDataCache.size <= MAX_CACHE_SIZE) {
    return;
  }
  const entries = Array.from(userDataCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);
  const entriesToRemove = Math.max(1, Math.floor(entries.length * 0.1));
  for (let i = 0; i < entriesToRemove; i++) {
    userDataCache.delete(entries[i][0]);
  }
  console.log(`[UserData] Cache eviction: removed ${entriesToRemove} oldest entries, size now ${userDataCache.size}`);
}
class UserDataError extends Error {
  constructor(message, userId, operation, originalError) {
    super(message);
    this.userId = userId;
    this.operation = operation;
    this.originalError = originalError;
    this.name = "UserDataError";
  }
}
async function getUserPlanAndFlags(userId) {
  const cached = userDataCache.get(userId);
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return {
      plan: cached.plan,
      flags: cached.flags,
      cached: true
    };
  }
  if (!isPoolHealthy()) {
    const error = new UserDataError(
      "Database pool is not healthy",
      userId,
      "getUserPlanAndFlags"
    );
    console.error("[UserData] Pool unhealthy:", error.message);
    if (!isDevelopment) {
      throw error;
    }
    console.warn("[UserData] Using defaults due to pool health check failure in development");
    return { plan: DEFAULT_PLAN, flags: DEFAULT_FLAGS, cached: false };
  }
  let client = null;
  try {
    client = await getPool().connect();
    const query = `
      SELECT
        "metaKey",
        "metaValue"
      FROM "users_metas"
      WHERE "userId" = $1
      AND "metaKey" IN ('user_plan', 'user_flags')
    `;
    const result = await client.query(query, [userId]);
    let plan = DEFAULT_PLAN;
    let flags = DEFAULT_FLAGS;
    for (const row of result.rows) {
      if (row.metaKey === "user_plan") {
        const planValue = row.metaValue;
        if (typeof planValue === "string" && ["free", "starter", "premium"].includes(planValue)) {
          plan = planValue;
        }
      } else if (row.metaKey === "user_flags") {
        const flagsValue = row.metaValue;
        if (Array.isArray(flagsValue)) {
          const validFlags = flagsValue.filter(
            (flag) => typeof flag === "string" && ["beta_tester", "early_adopter", "limited_access", "vip", "restricted", "experimental"].includes(flag)
          );
          flags = validFlags;
        }
      }
    }
    userDataCache.set(userId, {
      plan,
      flags,
      timestamp: Date.now()
    });
    evictOldestCacheEntries();
    return {
      plan,
      flags,
      cached: false
    };
  } catch (error) {
    const wrappedError = new UserDataError(
      `Failed to get user plan and flags: ${error instanceof Error ? error.message : "Unknown error"}`,
      userId,
      "getUserPlanAndFlags",
      error
    );
    console.error("[UserData] Error:", wrappedError.message, {
      userId,
      operation: "getUserPlanAndFlags",
      originalError: error
    });
    if (!isDevelopment) {
      throw wrappedError;
    }
    return {
      plan: DEFAULT_PLAN,
      flags: DEFAULT_FLAGS,
      cached: false
    };
  } finally {
    if (client) {
      client.release();
    }
  }
}
async function updateUserPlan(userId, plan) {
  if (!isPoolHealthy()) {
    const error = new UserDataError(
      "Database pool is not healthy",
      userId,
      "updateUserPlan"
    );
    console.error("[UserData] Pool unhealthy:", error.message);
    if (!isDevelopment) {
      throw error;
    }
    console.warn("[UserData] Using defaults due to pool health check failure in development");
    return false;
  }
  let client = null;
  try {
    client = await getPool().connect();
    const query = `
      INSERT INTO "users_metas" ("userId", "metaKey", "metaValue", "dataType", "updatedAt")
      VALUES ($1, 'user_plan', $2, 'string', CURRENT_TIMESTAMP)
      ON CONFLICT ("userId", "metaKey")
      DO UPDATE SET
        "metaValue" = EXCLUDED."metaValue",
        "updatedAt" = CURRENT_TIMESTAMP
    `;
    await client.query(query, [userId, plan]);
    userDataCache.delete(userId);
    return true;
  } catch (error) {
    const wrappedError = new UserDataError(
      `Failed to update user plan: ${error instanceof Error ? error.message : "Unknown error"}`,
      userId,
      "updateUserPlan",
      error
    );
    console.error("[UserData] Error:", wrappedError.message, {
      userId,
      operation: "updateUserPlan",
      plan,
      originalError: error
    });
    if (!isDevelopment) {
      throw wrappedError;
    }
    return false;
  } finally {
    if (client) {
      client.release();
    }
  }
}
async function updateUserFlags(userId, flags) {
  if (!isPoolHealthy()) {
    const error = new UserDataError(
      "Database pool is not healthy",
      userId,
      "updateUserFlags"
    );
    console.error("[UserData] Pool unhealthy:", error.message);
    if (!isDevelopment) {
      throw error;
    }
    console.warn("[UserData] Using defaults due to pool health check failure in development");
    return false;
  }
  let client = null;
  try {
    client = await getPool().connect();
    const query = `
      INSERT INTO "users_metas" ("userId", "metaKey", "metaValue", "dataType", "updatedAt")
      VALUES ($1, 'user_flags', $2, 'json', CURRENT_TIMESTAMP)
      ON CONFLICT ("userId", "metaKey")
      DO UPDATE SET
        "metaValue" = EXCLUDED."metaValue",
        "updatedAt" = CURRENT_TIMESTAMP
    `;
    await client.query(query, [userId, JSON.stringify(flags)]);
    userDataCache.delete(userId);
    return true;
  } catch (error) {
    const wrappedError = new UserDataError(
      `Failed to update user flags: ${error instanceof Error ? error.message : "Unknown error"}`,
      userId,
      "updateUserFlags",
      error
    );
    console.error("[UserData] Error:", wrappedError.message, {
      userId,
      operation: "updateUserFlags",
      flags,
      originalError: error
    });
    if (!isDevelopment) {
      throw wrappedError;
    }
    return false;
  } finally {
    if (client) {
      client.release();
    }
  }
}
async function enrichUserWithPlanData(user) {
  const planData = await getUserPlanAndFlags(user.id);
  return {
    ...user,
    plan: planData.plan,
    flags: planData.flags
  };
}
export {
  UserDataError,
  enrichUserWithPlanData,
  getUserPlanAndFlags,
  updateUserFlags,
  updateUserPlan
};
