import { CredentialType } from '@bubblelab/shared-schemas';
import { ServiceBubble } from '../../../types/service-bubble-class.js';
import { ClerkParamsSchema, ClerkResultSchema, } from './clerk.schema.js';
const CLERK_API_BASE = 'https://api.clerk.com/v1';
export class ClerkBubble extends ServiceBubble {
    static service = 'clerk';
    static authType = 'apikey';
    static bubbleName = 'clerk';
    static type = 'service';
    static schema = ClerkParamsSchema;
    static resultSchema = ClerkResultSchema;
    static shortDescription = 'Clerk integration for user management, organizations, and billing';
    static longDescription = `
    Integrate with Clerk to manage users, organizations, invitations, sessions, and billing.
    Supported operations:
    - Users: List, get, create, update, delete, ban, unban
    - Organizations: List, get, create, update, delete, list memberships
    - Invitations: List, create, revoke
    - Sessions: List, revoke
    - Billing: Get user/organization subscription status
    Authentication: OAuth 2.0 or Secret Key (Bearer token)
  `;
    static alias = 'clerk';
    constructor(params = {
        operation: 'list_users',
    }, context) {
        super(params, context);
    }
    chooseCredential() {
        const params = this.params;
        const credentials = params.credentials;
        if (!credentials || typeof credentials !== 'object') {
            return undefined;
        }
        return credentials[CredentialType.CLERK_CRED];
    }
    async makeClerkRequest(path, options = {}) {
        const token = this.chooseCredential();
        if (!token) {
            return { ok: false, error: 'Clerk credential not found' };
        }
        const { method = 'GET', body, queryParams } = options;
        let url = `${CLERK_API_BASE}${path}`;
        if (queryParams) {
            const params = new URLSearchParams(queryParams);
            url += `?${params.toString()}`;
        }
        const headers = {
            Authorization: `Bearer ${token}`,
            'Content-Type': 'application/json',
        };
        try {
            const fetchOptions = { method, headers };
            if (body && method !== 'GET') {
                fetchOptions.body = JSON.stringify(body);
            }
            const response = await fetch(url, fetchOptions);
            const text = await response.text();
            if (!response.ok) {
                let errorMessage = `Clerk API error (${response.status})`;
                try {
                    const errorData = JSON.parse(text);
                    errorMessage =
                        errorData.errors?.[0]?.long_message ||
                            errorData.errors?.[0]?.message ||
                            errorData.message ||
                            errorMessage;
                }
                catch {
                    if (text)
                        errorMessage += `: ${text.slice(0, 200)}`;
                }
                return { ok: false, error: errorMessage };
            }
            if (!text || text.trim() === '') {
                return { ok: true };
            }
            const data = JSON.parse(text);
            return { ok: true, data };
        }
        catch (error) {
            return {
                ok: false,
                error: error instanceof Error ? error.message : 'Unknown error occurred',
            };
        }
    }
    async testCredential() {
        const token = this.chooseCredential();
        if (!token) {
            throw new Error('Clerk credentials are required');
        }
        const response = await fetch(`${CLERK_API_BASE}/users?limit=1`, {
            method: 'GET',
            headers: {
                Authorization: `Bearer ${token}`,
                'Content-Type': 'application/json',
            },
        });
        if (!response.ok) {
            const text = await response.text();
            throw new Error(`Clerk API error (${response.status}): ${text}`);
        }
        return true;
    }
    async performAction(context) {
        void context;
        const params = this.params;
        const { operation } = params;
        try {
            switch (operation) {
                // Users
                case 'list_users':
                    return (await this.listUsers(params));
                case 'get_user':
                    return (await this.getUser(params));
                case 'create_user':
                    return (await this.createUser(params));
                case 'update_user':
                    return (await this.updateUser(params));
                case 'delete_user':
                    return (await this.deleteUser(params));
                case 'ban_user':
                    return (await this.banUser(params));
                case 'unban_user':
                    return (await this.unbanUser(params));
                // Organizations
                case 'list_organizations':
                    return (await this.listOrganizations(params));
                case 'get_organization':
                    return (await this.getOrganization(params));
                case 'create_organization':
                    return (await this.createOrganization(params));
                case 'update_organization':
                    return (await this.updateOrganization(params));
                case 'delete_organization':
                    return (await this.deleteOrganization(params));
                case 'list_organization_memberships':
                    return (await this.listOrganizationMemberships(params));
                // Invitations
                case 'list_invitations':
                    return (await this.listInvitations(params));
                case 'create_invitation':
                    return (await this.createInvitation(params));
                case 'revoke_invitation':
                    return (await this.revokeInvitation(params));
                // Sessions
                case 'list_sessions':
                    return (await this.listSessions(params));
                case 'revoke_session':
                    return (await this.revokeSession(params));
                // Billing
                case 'get_user_subscription':
                    return (await this.getUserSubscription(params));
                case 'get_organization_subscription':
                    return (await this.getOrganizationSubscription(params));
                default:
                    throw new Error(`Unknown operation: ${operation}`);
            }
        }
        catch (error) {
            return {
                operation,
                success: false,
                error: error instanceof Error ? error.message : 'Unknown error occurred',
            };
        }
    }
    // ========================== Users ==========================
    async listUsers(params) {
        const queryParams = {
            limit: String(params.limit),
            offset: String(params.offset),
        };
        if (params.order_by)
            queryParams.order_by = params.order_by;
        if (params.query)
            queryParams.query = params.query;
        if (params.email_address) {
            for (const email of params.email_address) {
                queryParams[`email_address[]`] = email;
            }
        }
        const result = await this.makeClerkRequest('/users', { queryParams });
        if (!result.ok) {
            return {
                operation: 'list_users',
                success: false,
                error: result.error || 'Failed to list users',
            };
        }
        const data = result.data;
        return {
            operation: 'list_users',
            users: data || [],
            total_count: Array.isArray(data) ? data.length : 0,
            success: true,
            error: '',
        };
    }
    async getUser(params) {
        const result = await this.makeClerkRequest(`/users/${encodeURIComponent(params.user_id)}`);
        if (!result.ok) {
            return {
                operation: 'get_user',
                success: false,
                error: result.error || 'Failed to get user',
            };
        }
        return {
            operation: 'get_user',
            user: result.data,
            success: true,
            error: '',
        };
    }
    async createUser(params) {
        const body = {
            email_address: params.email_address,
        };
        if (params.first_name)
            body.first_name = params.first_name;
        if (params.last_name)
            body.last_name = params.last_name;
        if (params.username)
            body.username = params.username;
        if (params.password)
            body.password = params.password;
        if (params.public_metadata)
            body.public_metadata = params.public_metadata;
        if (params.private_metadata)
            body.private_metadata = params.private_metadata;
        const result = await this.makeClerkRequest('/users', {
            method: 'POST',
            body,
        });
        if (!result.ok) {
            return {
                operation: 'create_user',
                success: false,
                error: result.error || 'Failed to create user',
            };
        }
        return {
            operation: 'create_user',
            user: result.data,
            success: true,
            error: '',
        };
    }
    async updateUser(params) {
        const body = {};
        if (params.first_name !== undefined)
            body.first_name = params.first_name;
        if (params.last_name !== undefined)
            body.last_name = params.last_name;
        if (params.username !== undefined)
            body.username = params.username;
        if (params.public_metadata)
            body.public_metadata = params.public_metadata;
        if (params.private_metadata)
            body.private_metadata = params.private_metadata;
        const result = await this.makeClerkRequest(`/users/${encodeURIComponent(params.user_id)}`, { method: 'PATCH', body });
        if (!result.ok) {
            return {
                operation: 'update_user',
                success: false,
                error: result.error || 'Failed to update user',
            };
        }
        return {
            operation: 'update_user',
            user: result.data,
            success: true,
            error: '',
        };
    }
    async deleteUser(params) {
        const result = await this.makeClerkRequest(`/users/${encodeURIComponent(params.user_id)}`, { method: 'DELETE' });
        return {
            operation: 'delete_user',
            success: result.ok,
            error: result.ok ? '' : result.error || 'Failed to delete user',
        };
    }
    async banUser(params) {
        const result = await this.makeClerkRequest(`/users/${encodeURIComponent(params.user_id)}/ban`, { method: 'POST' });
        if (!result.ok) {
            return {
                operation: 'ban_user',
                success: false,
                error: result.error || 'Failed to ban user',
            };
        }
        return {
            operation: 'ban_user',
            user: result.data,
            success: true,
            error: '',
        };
    }
    async unbanUser(params) {
        const result = await this.makeClerkRequest(`/users/${encodeURIComponent(params.user_id)}/unban`, { method: 'POST' });
        if (!result.ok) {
            return {
                operation: 'unban_user',
                success: false,
                error: result.error || 'Failed to unban user',
            };
        }
        return {
            operation: 'unban_user',
            user: result.data,
            success: true,
            error: '',
        };
    }
    // ========================== Organizations ==========================
    async listOrganizations(params) {
        const result = await this.makeClerkRequest('/organizations', {
            queryParams: {
                limit: String(params.limit),
                offset: String(params.offset),
            },
        });
        if (!result.ok) {
            return {
                operation: 'list_organizations',
                success: false,
                error: result.error || 'Failed to list organizations',
            };
        }
        const responseData = result.data;
        return {
            operation: 'list_organizations',
            organizations: responseData?.data || [],
            total_count: responseData?.total_count,
            success: true,
            error: '',
        };
    }
    async getOrganization(params) {
        const result = await this.makeClerkRequest(`/organizations/${encodeURIComponent(params.organization_id)}`);
        if (!result.ok) {
            return {
                operation: 'get_organization',
                success: false,
                error: result.error || 'Failed to get organization',
            };
        }
        return {
            operation: 'get_organization',
            organization: result.data,
            success: true,
            error: '',
        };
    }
    async createOrganization(params) {
        const body = { name: params.name };
        if (params.slug)
            body.slug = params.slug;
        if (params.created_by)
            body.created_by = params.created_by;
        if (params.public_metadata)
            body.public_metadata = params.public_metadata;
        if (params.private_metadata)
            body.private_metadata = params.private_metadata;
        if (params.max_allowed_memberships !== undefined)
            body.max_allowed_memberships = params.max_allowed_memberships;
        const result = await this.makeClerkRequest('/organizations', {
            method: 'POST',
            body,
        });
        if (!result.ok) {
            return {
                operation: 'create_organization',
                success: false,
                error: result.error || 'Failed to create organization',
            };
        }
        return {
            operation: 'create_organization',
            organization: result.data,
            success: true,
            error: '',
        };
    }
    async updateOrganization(params) {
        const body = {};
        if (params.name !== undefined)
            body.name = params.name;
        if (params.slug !== undefined)
            body.slug = params.slug;
        if (params.public_metadata)
            body.public_metadata = params.public_metadata;
        if (params.private_metadata)
            body.private_metadata = params.private_metadata;
        if (params.max_allowed_memberships !== undefined)
            body.max_allowed_memberships = params.max_allowed_memberships;
        const result = await this.makeClerkRequest(`/organizations/${encodeURIComponent(params.organization_id)}`, { method: 'PATCH', body });
        if (!result.ok) {
            return {
                operation: 'update_organization',
                success: false,
                error: result.error || 'Failed to update organization',
            };
        }
        return {
            operation: 'update_organization',
            organization: result.data,
            success: true,
            error: '',
        };
    }
    async deleteOrganization(params) {
        const result = await this.makeClerkRequest(`/organizations/${encodeURIComponent(params.organization_id)}`, { method: 'DELETE' });
        return {
            operation: 'delete_organization',
            success: result.ok,
            error: result.ok ? '' : result.error || 'Failed to delete organization',
        };
    }
    async listOrganizationMemberships(params) {
        const result = await this.makeClerkRequest(`/organizations/${encodeURIComponent(params.organization_id)}/memberships`, {
            queryParams: {
                limit: String(params.limit),
                offset: String(params.offset),
            },
        });
        if (!result.ok) {
            return {
                operation: 'list_organization_memberships',
                success: false,
                error: result.error || 'Failed to list memberships',
            };
        }
        const responseData = result.data;
        return {
            operation: 'list_organization_memberships',
            memberships: responseData?.data || [],
            total_count: responseData?.total_count,
            success: true,
            error: '',
        };
    }
    // ========================== Invitations ==========================
    async listInvitations(params) {
        const result = await this.makeClerkRequest('/invitations', {
            queryParams: {
                limit: String(params.limit),
                offset: String(params.offset),
            },
        });
        if (!result.ok) {
            return {
                operation: 'list_invitations',
                success: false,
                error: result.error || 'Failed to list invitations',
            };
        }
        const responseData = result.data;
        return {
            operation: 'list_invitations',
            invitations: responseData?.data || [],
            total_count: responseData?.total_count,
            success: true,
            error: '',
        };
    }
    async createInvitation(params) {
        const body = {
            email_address: params.email_address,
        };
        if (params.redirect_url)
            body.redirect_url = params.redirect_url;
        if (params.public_metadata)
            body.public_metadata = params.public_metadata;
        const result = await this.makeClerkRequest('/invitations', {
            method: 'POST',
            body,
        });
        if (!result.ok) {
            return {
                operation: 'create_invitation',
                success: false,
                error: result.error || 'Failed to create invitation',
            };
        }
        return {
            operation: 'create_invitation',
            invitation: result.data,
            success: true,
            error: '',
        };
    }
    async revokeInvitation(params) {
        const result = await this.makeClerkRequest(`/invitations/${encodeURIComponent(params.invitation_id)}/revoke`, { method: 'POST' });
        return {
            operation: 'revoke_invitation',
            success: result.ok,
            error: result.ok ? '' : result.error || 'Failed to revoke invitation',
        };
    }
    // ========================== Sessions ==========================
    async listSessions(params) {
        const queryParams = {
            limit: String(params.limit),
            offset: String(params.offset),
        };
        if (params.user_id)
            queryParams.user_id = params.user_id;
        if (params.status)
            queryParams.status = params.status;
        const result = await this.makeClerkRequest('/sessions', { queryParams });
        if (!result.ok) {
            return {
                operation: 'list_sessions',
                success: false,
                error: result.error || 'Failed to list sessions',
            };
        }
        const responseData = result.data;
        return {
            operation: 'list_sessions',
            sessions: responseData?.data || [],
            total_count: responseData?.total_count,
            success: true,
            error: '',
        };
    }
    async revokeSession(params) {
        const result = await this.makeClerkRequest(`/sessions/${encodeURIComponent(params.session_id)}/revoke`, { method: 'POST' });
        return {
            operation: 'revoke_session',
            success: result.ok,
            error: result.ok ? '' : result.error || 'Failed to revoke session',
        };
    }
    // ========================== Billing ==========================
    async getUserSubscription(params) {
        const result = await this.makeClerkRequest(`/users/${encodeURIComponent(params.user_id)}/billing/subscription`);
        if (!result.ok) {
            return {
                operation: 'get_user_subscription',
                success: false,
                error: result.error || 'Failed to get user subscription',
            };
        }
        return {
            operation: 'get_user_subscription',
            subscription: result.data,
            success: true,
            error: '',
        };
    }
    async getOrganizationSubscription(params) {
        const result = await this.makeClerkRequest(`/organizations/${encodeURIComponent(params.organization_id)}/billing/subscription`);
        if (!result.ok) {
            return {
                operation: 'get_organization_subscription',
                success: false,
                error: result.error || 'Failed to get organization subscription',
            };
        }
        return {
            operation: 'get_organization_subscription',
            subscription: result.data,
            success: true,
            error: '',
        };
    }
}
//# sourceMappingURL=clerk.js.map