import { CredentialType } from '@bubblelab/shared-schemas';
import { ServiceBubble } from '../../../types/service-bubble-class.js';
import { SlabParamsSchema, SlabResultSchema, } from './slab.schema.js';
// Slab GraphQL API endpoint
const SLAB_API_URL = 'https://api.slab.com/v1/graphql';
/**
 * SlabBubble - Integration with Slab knowledge management platform
 *
 * Provides operations for interacting with Slab:
 * - Search posts across the workspace
 * - Get specific post details
 * - List all organization posts
 * - Get posts within a topic
 * - List all topics
 *
 * @example
 * ```typescript
 * // Search for posts
 * const result = await new SlabBubble({
 *   operation: 'search_posts',
 *   query: 'onboarding guide',
 *   first: 10,
 * }).action();
 *
 * // Get a specific post
 * const post = await new SlabBubble({
 *   operation: 'get_post',
 *   post_id: 'abc123',
 * }).action();
 * ```
 */
export class SlabBubble extends ServiceBubble {
    // REQUIRED: Static metadata for BubbleFactory
    static service = 'slab';
    static authType = 'basic';
    static bubbleName = 'slab';
    static type = 'service';
    static schema = SlabParamsSchema;
    static resultSchema = SlabResultSchema;
    static shortDescription = 'Slab knowledge management for searching and managing posts';
    static longDescription = `
    Slab is a knowledge management platform for modern teams.
    This bubble provides operations for:
    - Searching posts across the workspace
    - Retrieving specific post details and content
    - Listing all organization posts
    - Getting posts within specific topics
    - Listing all topics in the organization

    Authentication:
    - Uses API token (available on Business/Enterprise plans)
    - Token is passed via Authorization header

    Use Cases:
    - Search internal knowledge base from automated workflows
    - Sync documentation with external systems
    - Build AI assistants that leverage internal knowledge
    - Automate content updates across the organization
  `;
    static alias = 'slab-kb';
    constructor(params = {
        operation: 'search_posts',
        query: '',
    }, context) {
        super(params, context);
    }
    /**
     * Choose the appropriate credential for Slab API
     */
    chooseCredential() {
        const params = this.params;
        const credentials = params.credentials;
        if (!credentials || typeof credentials !== 'object') {
            return undefined;
        }
        return credentials[CredentialType.SLAB_CRED];
    }
    /**
     * Test if the credential is valid by making a simple API call
     */
    async testCredential() {
        const apiToken = this.chooseCredential();
        if (!apiToken) {
            return false;
        }
        // Use a simple query to validate the token
        const result = await this.makeSlabRequest(`
      query {
        organization {
          name
        }
      }
    `);
        if (result.errors) {
            throw new Error('Slab API token validation failed');
        }
        return true;
    }
    /**
     * Perform the Slab operation
     */
    async performAction(context) {
        void context;
        const params = this.params;
        const { operation } = params;
        try {
            switch (operation) {
                case 'search_posts':
                    return (await this.searchPosts(params));
                case 'get_post':
                    return (await this.getPost(params));
                case 'list_posts':
                    return (await this.listPosts(params));
                case 'get_topic_posts':
                    return (await this.getTopicPosts(params));
                case 'list_topics':
                    return (await this.listTopics(params));
                default:
                    throw new Error(`Unknown operation: ${operation}`);
            }
        }
        catch (error) {
            const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
            return {
                operation,
                success: false,
                error: errorMessage,
            };
        }
    }
    /**
     * Make an authenticated GraphQL request to Slab
     */
    async makeSlabRequest(query, variables) {
        const apiToken = this.chooseCredential();
        if (!apiToken) {
            throw new Error('Slab API token is required');
        }
        const response = await fetch(SLAB_API_URL, {
            method: 'POST',
            headers: {
                Authorization: `${apiToken}`,
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ query, variables }),
        });
        if (!response.ok) {
            const text = await response.text();
            throw new Error(`Slab API error (HTTP ${response.status}): ${text}`);
        }
        const data = (await response.json());
        if (data.errors) {
            const errors = data.errors;
            const errorMsg = errors
                .map((e) => e.message || 'Unknown error')
                .join('; ');
            throw new Error(`Slab GraphQL error: ${errorMsg}`);
        }
        return data;
    }
    /**
     * Search posts by query
     */
    async searchPosts(params) {
        const response = await this.makeSlabRequest(`
      query SearchPosts($query: String!, $first: Int, $after: String) {
        search(query: $query, first: $first, after: $after) {
          pageInfo {
            hasNextPage
            endCursor
          }
          edges {
            cursor
            node {
              ... on PostSearchResult {
                title
                content
                highlight
                post {
                  id
                  title
                  insertedAt
                  publishedAt
                  owner {
                    id
                    name
                  }
                  topics {
                    id
                    name
                  }
                }
              }
            }
          }
        }
      }
    `, {
            query: params.query,
            first: params.first,
            after: params.after,
        });
        const searchData = response.data?.search;
        const edges = searchData?.edges || [];
        const pageInfo = searchData?.pageInfo;
        const posts = edges
            .map((edge) => {
            const node = edge.node;
            if (!node || !node.post)
                return null;
            const post = node.post;
            return {
                id: post.id,
                title: node.title || post.title,
                highlight: node.highlight,
                content: node.content,
                insertedAt: post.insertedAt,
                publishedAt: post.publishedAt,
                owner: post.owner,
                topics: post.topics,
            };
        })
            .filter((p) => p !== null);
        return {
            operation: 'search_posts',
            success: true,
            posts,
            has_more: pageInfo?.hasNextPage || false,
            end_cursor: pageInfo?.endCursor,
            error: '',
        };
    }
    /**
     * Get a specific post by ID
     */
    async getPost(params) {
        const response = await this.makeSlabRequest(`
      query GetPost($id: ID!) {
        post(id: $id) {
          id
          title
          content
          insertedAt
          publishedAt
          updatedAt
          archivedAt
          version
          owner {
            id
            name
          }
          topics {
            id
            name
          }
        }
      }
    `, { id: params.post_id });
        const post = response.data?.post;
        return {
            operation: 'get_post',
            success: true,
            post: post
                ? {
                    id: post.id,
                    title: post.title,
                    content: post.content,
                    insertedAt: post.insertedAt,
                    publishedAt: post.publishedAt,
                    updatedAt: post.updatedAt,
                    archivedAt: post.archivedAt,
                    version: post.version,
                    owner: post.owner,
                    topics: post.topics,
                }
                : undefined,
            error: '',
        };
    }
    /**
     * List all organization posts
     */
    async listPosts(params) {
        void params;
        // organization.posts returns SlimPost type (limited fields)
        const response = await this.makeSlabRequest(`
      query {
        organization {
          posts {
            id
            title
            publishedAt
            archivedAt
          }
        }
      }
    `);
        const org = response.data?.organization;
        const posts = org?.posts || [];
        return {
            operation: 'list_posts',
            success: true,
            posts: posts.map((p) => ({
                id: p.id,
                title: p.title,
                publishedAt: p.publishedAt,
                archivedAt: p.archivedAt,
            })),
            error: '',
        };
    }
    /**
     * Get posts within a specific topic
     */
    async getTopicPosts(params) {
        const response = await this.makeSlabRequest(`
      query GetTopicPosts($id: ID!) {
        topic(id: $id) {
          posts {
            id
            title
            content
            insertedAt
            publishedAt
            updatedAt
            owner {
              id
              name
            }
          }
        }
      }
    `, { id: params.topic_id });
        const topic = response.data?.topic;
        const posts = topic?.posts || [];
        return {
            operation: 'get_topic_posts',
            success: true,
            posts: posts.map((p) => ({
                id: p.id,
                title: p.title,
                content: p.content,
                insertedAt: p.insertedAt,
                publishedAt: p.publishedAt,
                updatedAt: p.updatedAt,
                owner: p.owner,
            })),
            error: '',
        };
    }
    /**
     * List all topics in the organization
     */
    async listTopics(params) {
        void params;
        const response = await this.makeSlabRequest(`
      query {
        organization {
          topics {
            id
            name
          }
        }
      }
    `);
        const org = response.data?.organization;
        const topics = org?.topics || [];
        return {
            operation: 'list_topics',
            success: true,
            topics: topics.map((t) => ({
                id: t.id,
                name: t.name,
            })),
            error: '',
        };
    }
}
//# sourceMappingURL=slab.js.map