import {
  init_ids,
  newId
} from "./chunk-F4WUVOLE.js";
import {
  init_clock,
  nowMs
} from "./chunk-HFDLUBWN.js";
import {
  getDrizzle,
  init_drizzle
} from "./chunk-RII4M3J2.js";
import {
  schema_exports
} from "./chunk-DDJOPRB7.js";

// src/db/api_keys.ts
init_drizzle();
init_ids();
init_clock();
import crypto from "crypto";
import { eq, and, desc, isNull, sql } from "drizzle-orm";
function hashKey(raw) {
  return crypto.createHash("sha256").update(raw).digest("hex");
}
function hydratePermissions(json) {
  try {
    const parsed = JSON.parse(json);
    if (Array.isArray(parsed)) {
      return { admin: true, scope: null };
    }
    if (parsed && typeof parsed === "object") {
      const admin = parsed.admin === true;
      const scope = parsed.scope && typeof parsed.scope === "object" ? normalizeScope(parsed.scope) : null;
      return { admin, scope };
    }
  } catch {
  }
  return { admin: false, scope: null };
}
function normalizeScope(raw) {
  const list = (v) => {
    if (!Array.isArray(v)) return [];
    return v.filter((x) => typeof x === "string");
  };
  return {
    agents: list(raw.agents),
    environments: list(raw.environments),
    vaults: list(raw.vaults)
  };
}
function createApiKey(input) {
  const db = getDrizzle();
  const id = newId("key");
  const raw = input.rawKey || `ck_${crypto.randomBytes(24).toString("base64url")}`;
  const hash = hashKey(raw);
  const prefix = raw.slice(0, 8);
  const permissionsJson = input.permissions == null ? JSON.stringify({ admin: true, scope: null }) : Array.isArray(input.permissions) ? JSON.stringify(input.permissions) : JSON.stringify(input.permissions);
  db.insert(schema_exports.apiKeys).values({
    id,
    name: input.name,
    hash,
    prefix,
    permissions_json: permissionsJson,
    tenant_id: input.tenantId ?? null,
    budget_usd: input.budgetUsd ?? null,
    rate_limit_rpm: input.rateLimitRpm ?? null,
    spent_usd: 0,
    created_at: nowMs()
  }).run();
  return { key: raw, id };
}
function bumpKeySpent(keyId, deltaUsd) {
  if (!keyId || !Number.isFinite(deltaUsd) || deltaUsd === 0) return;
  const db = getDrizzle();
  db.update(schema_exports.apiKeys).set({ spent_usd: sql`${schema_exports.apiKeys.spent_usd} + ${deltaUsd}` }).where(eq(schema_exports.apiKeys.id, keyId)).run();
}
function resetKeySpent(keyId) {
  const db = getDrizzle();
  const res = db.update(schema_exports.apiKeys).set({ spent_usd: 0 }).where(eq(schema_exports.apiKeys.id, keyId)).run();
  return res.changes > 0;
}
function updateApiKeyLimits(id, limits) {
  const db = getDrizzle();
  const updates = {};
  if ("budgetUsd" in limits) {
    updates.budget_usd = limits.budgetUsd ?? null;
  }
  if ("rateLimitRpm" in limits) {
    updates.rate_limit_rpm = limits.rateLimitRpm ?? null;
  }
  if (Object.keys(updates).length === 0) return false;
  const res = db.update(schema_exports.apiKeys).set(updates).where(and(eq(schema_exports.apiKeys.id, id), isNull(schema_exports.apiKeys.revoked_at))).run();
  return res.changes > 0;
}
function findByRawKey(raw) {
  const db = getDrizzle();
  const hash = hashKey(raw);
  const row = db.select().from(schema_exports.apiKeys).where(and(eq(schema_exports.apiKeys.hash, hash), isNull(schema_exports.apiKeys.revoked_at))).get();
  return row ?? null;
}
function getApiKeyById(id) {
  const db = getDrizzle();
  const row = db.select().from(schema_exports.apiKeys).where(eq(schema_exports.apiKeys.id, id)).get();
  return row ?? null;
}
function revokeApiKey(id) {
  const db = getDrizzle();
  const res = db.update(schema_exports.apiKeys).set({ revoked_at: nowMs() }).where(and(eq(schema_exports.apiKeys.id, id), isNull(schema_exports.apiKeys.revoked_at))).run();
  return res.changes > 0;
}
function updateApiKeyPermissions(id, permissions) {
  const db = getDrizzle();
  const res = db.update(schema_exports.apiKeys).set({ permissions_json: JSON.stringify(permissions) }).where(and(eq(schema_exports.apiKeys.id, id), isNull(schema_exports.apiKeys.revoked_at))).run();
  return res.changes > 0;
}
function toView(r) {
  return {
    id: r.id,
    name: r.name,
    prefix: r.prefix,
    permissions: hydratePermissions(r.permissions_json),
    tenant_id: r.tenant_id,
    budget_usd: r.budget_usd,
    rate_limit_rpm: r.rate_limit_rpm,
    spent_usd: r.spent_usd ?? 0,
    created_at: r.created_at
  };
}
function listApiKeys(opts = {}) {
  const db = getDrizzle();
  const conditions = [isNull(schema_exports.apiKeys.revoked_at)];
  if (opts.tenantFilter != null) {
    conditions.push(eq(schema_exports.apiKeys.tenant_id, opts.tenantFilter));
  }
  const rows = db.select().from(schema_exports.apiKeys).where(and(...conditions)).orderBy(desc(schema_exports.apiKeys.created_at)).all();
  return rows.map(toView);
}

export {
  hydratePermissions,
  createApiKey,
  bumpKeySpent,
  resetKeySpent,
  updateApiKeyLimits,
  findByRawKey,
  getApiKeyById,
  revokeApiKey,
  updateApiKeyPermissions,
  toView,
  listApiKeys
};
