// src/lib/auth/providers/betterAuth.ts
import { createProxyFetch } from "../../proxy/proxyFetch.js";
import { AuthError } from "../errors.js";
import * as jose from "jose";
import { BaseAuthProvider } from "./BaseAuthProvider.js";
/**
 * Better Auth Provider
 *
 * Supports Better Auth, a self-hosted open-source authentication solution.
 * Validates session tokens and JWTs issued by Better Auth server.
 *
 * Features:
 * - JWT validation using HMAC secret
 * - Session validation via Better Auth API
 * - Social provider support (GitHub, Google, Discord)
 * - Session management (inherited from BaseAuthProvider)
 *
 * @example
 * ```typescript
 * const betterAuth = new BetterAuthProvider({
 *   type: "better-auth",
 *   secret: "your-better-auth-secret",
 *   baseUrl: "https://your-app.com"
 * });
 *
 * const result = await betterAuth.authenticateToken(sessionToken);
 * if (result.valid) {
 *   console.log("Authenticated user:", result.user);
 * }
 * ```
 */
export class BetterAuthProvider extends BaseAuthProvider {
    type = "better-auth";
    secret;
    baseUrl;
    secretKey;
    constructor(config) {
        super(config);
        if (!config.secret) {
            throw AuthError.create("CONFIGURATION_ERROR", "Better Auth secret is required", { details: { provider: "better-auth", missingFields: ["secret"] } });
        }
        if (!config.baseUrl) {
            throw AuthError.create("CONFIGURATION_ERROR", "Better Auth baseUrl is required", { details: { provider: "better-auth", missingFields: ["baseUrl"] } });
        }
        this.secret = config.secret;
        this.baseUrl = config.baseUrl.replace(/\/$/, ""); // Remove trailing slash
        this.secretKey = new TextEncoder().encode(this.secret);
    }
    /**
     * Validate Better Auth token (session or JWT)
     */
    async authenticateToken(token, _context) {
        // Try JWT validation first (if it looks like a JWT)
        if (token.includes(".") && token.split(".").length === 3) {
            const jwtResult = await this.validateJWT(token);
            if (jwtResult.valid) {
                return jwtResult;
            }
        }
        // Fall back to session validation via API
        return this.validateSessionViaAPI(token);
    }
    /**
     * Validate JWT using the secret
     */
    async validateJWT(token) {
        try {
            const { payload } = await jose.jwtVerify(token, this.secretKey);
            if (!payload.sub) {
                return {
                    valid: false,
                    error: "Token missing required 'sub' claim",
                };
            }
            const user = {
                id: payload.sub,
                email: payload.email,
                name: payload.name,
                picture: payload.picture,
                emailVerified: payload.email_verified,
                roles: payload.roles || [],
                permissions: payload.permissions || [],
                metadata: payload.metadata,
            };
            return {
                valid: true,
                payload: payload,
                user,
                expiresAt: payload.exp ? new Date(payload.exp * 1000) : undefined,
                tokenType: "jwt",
            };
        }
        catch (error) {
            return {
                valid: false,
                error: error instanceof Error ? error.message : String(error),
            };
        }
    }
    /**
     * Validate session via Better Auth API
     */
    async validateSessionViaAPI(sessionToken) {
        try {
            const proxyFetch = createProxyFetch();
            const response = await proxyFetch(`${this.baseUrl}/api/auth/session`, {
                headers: {
                    Cookie: `better-auth.session_token=${sessionToken}`,
                },
                signal: AbortSignal.timeout(5000),
            });
            if (!response.ok) {
                return {
                    valid: false,
                    error: `Session validation failed: HTTP ${response.status}`,
                };
            }
            const session = (await response.json());
            if (!session.user) {
                return {
                    valid: false,
                    error: "Invalid session",
                };
            }
            const user = {
                id: session.user.id,
                email: session.user.email,
                name: session.user.name,
                picture: session.user.image,
                emailVerified: session.user.emailVerified,
                roles: session.user.roles || [],
                permissions: session.user.permissions || [],
                createdAt: session.user.createdAt
                    ? new Date(session.user.createdAt)
                    : undefined,
                metadata: session.user,
            };
            return {
                valid: true,
                payload: session,
                user,
                expiresAt: session.session?.expiresAt
                    ? new Date(session.session.expiresAt)
                    : undefined,
                tokenType: "session",
            };
        }
        catch (error) {
            return {
                valid: false,
                error: error instanceof Error ? error.message : String(error),
            };
        }
    }
    /**
     * Health check
     */
    async healthCheck() {
        try {
            const proxyFetch = createProxyFetch();
            // Better Auth typically exposes session endpoint that we can check
            const response = await proxyFetch(`${this.baseUrl}/api/auth/session`, {
                signal: AbortSignal.timeout(5000),
            });
            // Even a 401 means the endpoint is working
            const isReachable = response.status < 500;
            return {
                healthy: isReachable,
                providerConnected: isReachable,
                sessionStorageHealthy: true,
            };
        }
        catch (error) {
            return {
                healthy: false,
                providerConnected: false,
                sessionStorageHealthy: true,
                error: error instanceof Error ? error.message : String(error),
            };
        }
    }
}
//# sourceMappingURL=betterAuth.js.map