import {
  tenantFilter
} from "./chunk-K7DLILHK.js";
import {
  jsonOk,
  routeWrap
} from "./chunk-QSHK4MUE.js";
import {
  getUserProfile,
  updateUserProfile
} from "./chunk-SK4OB66U.js";
import {
  createCredential,
  getCredential,
  updateCredential
} from "./chunk-7T3L22TP.js";
import {
  badRequest,
  notFound
} from "./chunk-EZYKRG4W.js";

// src/handlers/anthropic-compat/enrollment.ts
import { z } from "zod";
import { randomBytes } from "crypto";
var pendingEnrollments = /* @__PURE__ */ new Map();
setInterval(() => {
  const cutoff = Date.now() - 10 * 6e4;
  for (const [state, enrollment] of pendingEnrollments) {
    if (enrollment.createdAt < cutoff) pendingEnrollments.delete(state);
  }
}, 6e4);
var EnrollmentSchema = z.object({
  vault_id: z.string().min(1),
  credential_id: z.string().optional(),
  // update existing credential, or omit to create new
  display_name: z.string().min(1).optional(),
  // required when creating new
  authorize_url: z.string().url(),
  token_endpoint: z.string().url(),
  client_id: z.string().min(1),
  client_secret: z.string().optional(),
  scope: z.string().optional(),
  redirect_uri: z.string().url().optional()
});
function handleEnrollmentUrl(request, profileId) {
  return routeWrap(request, async ({ auth }) => {
    const profile = getUserProfile(profileId);
    if (!profile) throw notFound(`user profile not found: ${profileId}`);
    const filter = tenantFilter(auth);
    if (filter && profile.tenant_id !== filter) {
      throw notFound(`user profile not found: ${profileId}`);
    }
    const body = await request.json().catch(() => null);
    const parsed = EnrollmentSchema.safeParse(body);
    if (!parsed.success) {
      throw badRequest(`invalid body: ${parsed.error.issues.map((i) => i.message).join("; ")}`);
    }
    const data = parsed.data;
    if (data.credential_id) {
      const cred = getCredential(data.credential_id);
      if (!cred || cred.vault_id !== data.vault_id) {
        throw badRequest(`credential not found: ${data.credential_id}`);
      }
    } else if (!data.display_name) {
      throw badRequest("display_name is required when creating a new credential");
    }
    const state = randomBytes(32).toString("hex");
    const reqUrl = new URL(request.url);
    const redirectUri = data.redirect_uri || `${reqUrl.origin}/v1/oauth/callback`;
    pendingEnrollments.set(state, {
      profileId,
      vaultId: data.vault_id,
      credentialId: data.credential_id ?? null,
      tokenEndpoint: data.token_endpoint,
      clientId: data.client_id,
      clientSecret: data.client_secret,
      scope: data.scope,
      redirectUri,
      createdAt: Date.now()
    });
    const params = new URLSearchParams({
      response_type: "code",
      client_id: data.client_id,
      redirect_uri: redirectUri,
      state,
      ...data.scope ? { scope: data.scope } : {}
    });
    const url = `${data.authorize_url}?${params.toString()}`;
    return jsonOk({
      type: "enrollment_url",
      url,
      state,
      redirect_uri: redirectUri,
      expires_in: 600
      // 10 minutes
    });
  });
}
async function handleOAuthCallback(request) {
  const { ensureInitialized } = await import("./init.js");
  await ensureInitialized();
  try {
    const url = new URL(request.url);
    const code = url.searchParams.get("code");
    const state = url.searchParams.get("state");
    const error = url.searchParams.get("error");
    if (error) {
      return new Response(
        `<html><body><h2>Authorization failed</h2><p>${error}</p></body></html>`,
        { status: 400, headers: { "Content-Type": "text/html" } }
      );
    }
    if (!code || !state) {
      return new Response(
        `<html><body><h2>Missing code or state parameter</h2></body></html>`,
        { status: 400, headers: { "Content-Type": "text/html" } }
      );
    }
    const enrollment = pendingEnrollments.get(state);
    if (!enrollment) {
      return new Response(
        `<html><body><h2>Invalid or expired enrollment state</h2><p>Please restart the enrollment process.</p></body></html>`,
        { status: 400, headers: { "Content-Type": "text/html" } }
      );
    }
    pendingEnrollments.delete(state);
    const body = new URLSearchParams({
      grant_type: "authorization_code",
      code,
      client_id: enrollment.clientId,
      redirect_uri: enrollment.redirectUri,
      ...enrollment.scope ? { scope: enrollment.scope } : {}
    });
    if (enrollment.clientSecret) {
      body.set("client_secret", enrollment.clientSecret);
    }
    const tokenRes = await fetch(enrollment.tokenEndpoint, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: body.toString(),
      signal: AbortSignal.timeout(15e3)
    });
    if (!tokenRes.ok) {
      const errText = await tokenRes.text().catch(() => "");
      return new Response(
        `<html><body><h2>Token exchange failed</h2><p>${tokenRes.status}: ${errText.slice(0, 200)}</p></body></html>`,
        { status: 502, headers: { "Content-Type": "text/html" } }
      );
    }
    const tokens = await tokenRes.json();
    let credentialId;
    const expiresAt = tokens.expires_in ? new Date(Date.now() + tokens.expires_in * 1e3).toISOString() : null;
    const refreshConfig = tokens.refresh_token ? {
      token_endpoint: enrollment.tokenEndpoint,
      client_id: enrollment.clientId,
      scope: enrollment.scope ?? tokens.scope,
      refresh_token: tokens.refresh_token,
      ...enrollment.clientSecret ? { token_endpoint_auth: { type: "client_secret_post", client_secret: enrollment.clientSecret } } : {}
    } : null;
    if (enrollment.credentialId) {
      updateCredential(enrollment.credentialId, {
        auth_type: "mcp_oauth",
        token: tokens.access_token,
        expires_at: expiresAt,
        refresh_config: refreshConfig
      });
      credentialId = enrollment.credentialId;
    } else {
      const profile2 = getUserProfile(enrollment.profileId);
      const displayName = `oauth-${enrollment.clientId}-${Date.now()}`;
      const cred = createCredential({
        vault_id: enrollment.vaultId,
        display_name: displayName,
        auth_type: "mcp_oauth",
        token: tokens.access_token,
        expires_at: expiresAt,
        refresh_config: refreshConfig
      });
      credentialId = cred.id;
    }
    const profile = getUserProfile(enrollment.profileId);
    if (profile) {
      const existingGrant = profile.trust_grants.find(
        (g) => g.vault_id === enrollment.vaultId && g.credential_id === credentialId
      );
      if (!existingGrant) {
        const newGrants = [
          ...profile.trust_grants,
          { type: "vault_credential", vault_id: enrollment.vaultId, credential_id: credentialId }
        ];
        updateUserProfile(enrollment.profileId, { trust_grants: newGrants });
      }
    }
    return new Response(
      `<html><body><h2>Enrollment complete</h2><p>Credential ${credentialId} has been linked to your profile. You can close this window.</p></body></html>`,
      { status: 200, headers: { "Content-Type": "text/html" } }
    );
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    return new Response(
      `<html><body><h2>Enrollment error</h2><p>${msg}</p></body></html>`,
      { status: 500, headers: { "Content-Type": "text/html" } }
    );
  }
}

export {
  handleEnrollmentUrl,
  handleOAuthCallback
};
