import { ServiceBubble } from '../../../types/service-bubble-class.js';
import { CredentialType } from '@bubblelab/shared-schemas';
import { FullEnrichParamsSchema, FullEnrichResultSchema, } from './fullenrich.schema.js';
/**
 * FullEnrich Service Bubble
 *
 * B2B contact enrichment service for finding work emails, mobile phones,
 * and personal emails from contact information or LinkedIn profiles.
 *
 * Features:
 * - Bulk enrichment for up to 100 contacts at once
 * - Reverse email lookup to find contact info from email addresses
 * - LinkedIn profile enrichment for enhanced data
 * - Webhook support for real-time result delivery
 * - Credit-based pricing with balance tracking
 *
 * Use cases:
 * - Enrich leads with work emails and phone numbers
 * - Build sales prospecting pipelines
 * - Verify and update CRM contact data
 * - Find decision makers from LinkedIn profiles
 *
 * Credit Costs:
 * - Work email: 1 credit
 * - Personal email: 3 credits
 * - Mobile phone: 10 credits
 * - Reverse email lookup: 1 credit per match
 *
 * Security Features:
 * - API key authentication (Bearer token)
 * - Workspace-based access control
 * - Rate limiting protection
 */
export class FullEnrichBubble extends ServiceBubble {
    static type = 'service';
    static service = 'fullenrich';
    static authType = 'apikey';
    static bubbleName = 'fullenrich';
    static schema = FullEnrichParamsSchema;
    static resultSchema = FullEnrichResultSchema;
    static shortDescription = 'B2B contact enrichment for emails, phones, and LinkedIn data';
    static longDescription = `
    FullEnrich B2B contact enrichment service for finding work emails,
    mobile phones, and personal emails from contact information or LinkedIn profiles.

    Features:
    - Bulk enrichment for up to 100 contacts at once
    - Reverse email lookup to find contact info from email addresses
    - LinkedIn profile enrichment for enhanced data (+5-20% better email rates, +10-60% better phone rates)
    - Webhook support for real-time result delivery
    - Credit-based pricing with balance tracking

    Use cases:
    - Enrich leads with work emails and phone numbers
    - Build sales prospecting pipelines
    - Verify and update CRM contact data
    - Find decision makers from LinkedIn profiles

    Credit Costs:
    - Work email: 1 credit
    - Personal email: 3 credits
    - Mobile phone: 10 credits
    - Reverse email lookup: 1 credit per match

    Security Features:
    - API key authentication (Bearer token)
    - Workspace-based access control
    - Rate limiting protection
  `;
    static alias = 'enrich';
    static BASE_URL = 'https://app.fullenrich.com/api/v1';
    constructor(params = {
        operation: 'get_credit_balance',
    }, context, instanceId) {
        super(params, context, instanceId);
    }
    /**
     * Test if the API key is valid
     */
    async testCredential() {
        const credential = this.chooseCredential();
        if (!credential) {
            return false;
        }
        const response = await fetch(`${FullEnrichBubble.BASE_URL}/account/keys/verify`, {
            method: 'GET',
            headers: {
                Authorization: `Bearer ${credential}`,
                'Content-Type': 'application/json',
            },
        });
        if (!response.ok) {
            const errorText = await response.text().catch(() => '');
            throw new Error(`FullEnrich API key verification failed (${response.status}): ${errorText}`);
        }
        return true;
    }
    /**
     * Make an API request to FullEnrich
     */
    async makeApiRequest(endpoint, method = 'GET', body) {
        const credential = this.chooseCredential();
        if (!credential) {
            throw new Error('FullEnrich API key is required');
        }
        const url = `${FullEnrichBubble.BASE_URL}${endpoint}`;
        const headers = {
            Authorization: `Bearer ${credential}`,
            'Content-Type': 'application/json',
        };
        const requestInit = {
            method,
            headers,
        };
        if (body && method !== 'GET') {
            requestInit.body = JSON.stringify(body);
        }
        const response = await fetch(url, requestInit);
        if (!response.ok) {
            let errorMessage = `FullEnrich API error: ${response.status} ${response.statusText}`;
            try {
                const errorData = (await response.json());
                if (errorData.message) {
                    errorMessage = `FullEnrich API error: ${errorData.message} (${errorData.code})`;
                }
            }
            catch {
                // If we can't parse the error response, use the default message
            }
            throw new Error(errorMessage);
        }
        return (await response.json());
    }
    /**
     * Main action handler - routes to appropriate operation
     */
    async performAction(context) {
        void context;
        const { operation } = this.params;
        try {
            const result = await (async () => {
                // Cast to output type since base class already parsed input through Zod
                const parsedParams = this.params;
                switch (operation) {
                    case 'start_bulk_enrichment':
                        return await this.startBulkEnrichment(parsedParams);
                    case 'get_enrichment_result':
                        return await this.getEnrichmentResult(parsedParams);
                    case 'start_reverse_email_lookup':
                        return await this.startReverseEmailLookup(parsedParams);
                    case 'get_reverse_email_result':
                        return await this.getReverseEmailResult(parsedParams);
                    case 'get_credit_balance':
                        return await this.getCreditBalance(parsedParams);
                    case 'check_api_key':
                        return await this.checkApiKey(parsedParams);
                    default:
                        throw new Error(`Unsupported operation: ${operation}`);
                }
            })();
            return result;
        }
        catch (error) {
            return {
                operation,
                success: false,
                error: error instanceof Error ? error.message : 'Unknown error occurred',
            };
        }
    }
    /**
     * Start bulk enrichment for contacts
     */
    async startBulkEnrichment(params) {
        const { name, webhook_url, contacts } = params;
        // Transform contacts to API format
        const datas = contacts.map((contact) => ({
            firstname: contact.firstname,
            lastname: contact.lastname,
            domain: contact.domain,
            company_name: contact.company_name,
            linkedin_url: contact.linkedin_url,
            enrich_fields: contact.enrich_fields,
            custom: contact.custom,
        }));
        const body = {
            name,
            datas,
        };
        if (webhook_url) {
            body.webhook_url = webhook_url;
        }
        const response = await this.makeApiRequest('/contact/enrich/bulk', 'POST', body);
        return {
            operation: 'start_bulk_enrichment',
            success: true,
            enrichment_id: response.enrichment_id,
            error: '',
        };
    }
    /**
     * Get enrichment result by ID
     */
    async getEnrichmentResult(params) {
        const { enrichment_id, force_results } = params;
        const queryParams = new URLSearchParams();
        if (force_results) {
            queryParams.set('forceResults', 'true');
        }
        const queryString = queryParams.toString();
        const endpoint = `/contact/enrich/bulk/${enrichment_id}${queryString ? `?${queryString}` : ''}`;
        const response = await this.makeApiRequest(endpoint, 'GET');
        const result = {
            operation: 'get_enrichment_result',
            success: true,
            id: response.id,
            name: response.name,
            status: response.status,
            results: response.datas,
            cost: response.cost,
            error: '',
        };
        // Track usage: count emails found (work emails + personal emails)
        if (result.success &&
            result.status === 'FINISHED' &&
            result.results &&
            this.context &&
            this.context.logger) {
            const logger = this.context.logger;
            let emailCount = 0;
            for (const record of result.results) {
                const contact = record.contact;
                if (contact) {
                    // Count work emails
                    if (Array.isArray(contact.emails)) {
                        emailCount += contact.emails.length;
                    }
                    // Count personal emails
                    if (Array.isArray(contact.personal_emails)) {
                        emailCount += contact.personal_emails.length;
                    }
                }
            }
            if (emailCount > 0) {
                logger.logTokenUsage({
                    usage: emailCount,
                    service: CredentialType.FULLENRICH_API_KEY,
                    unit: 'per_email',
                }, `FullEnrich enrichment: ${emailCount} email(s) found`, {
                    bubbleName: 'fullenrich',
                    variableId: this.context?.variableId,
                    operationType: 'bubble_execution',
                });
            }
        }
        return result;
    }
    /**
     * Start reverse email lookup
     */
    async startReverseEmailLookup(params) {
        const { name, webhook_url, emails } = params;
        // Transform emails to API format
        const data = emails.map((email) => ({ email }));
        const body = {
            name,
            data,
        };
        if (webhook_url) {
            body.webhook_url = webhook_url;
        }
        const response = await this.makeApiRequest('/contact/reverse/email/bulk', 'POST', body);
        return {
            operation: 'start_reverse_email_lookup',
            success: true,
            enrichment_id: response.enrichment_id,
            error: '',
        };
    }
    /**
     * Get reverse email lookup result
     */
    async getReverseEmailResult(params) {
        const { reverse_email_id } = params;
        const response = await this.makeApiRequest(`/contact/reverse/email/bulk/${reverse_email_id}`, 'GET');
        const result = {
            operation: 'get_reverse_email_result',
            success: true,
            id: response.id,
            name: response.name,
            status: response.status,
            results: response.datas,
            cost: response.cost,
            error: '',
        };
        // Track usage: count successful matches (emails with contact data found)
        if (result.success &&
            result.status === 'FINISHED' &&
            result.results &&
            this.context &&
            this.context.logger) {
            const logger = this.context.logger;
            let matchCount = 0;
            for (const record of result.results) {
                // Count as a match if contact data was found
                if (record.contact) {
                    matchCount += 1;
                }
            }
            if (matchCount > 0) {
                logger.logTokenUsage({
                    usage: matchCount,
                    service: CredentialType.FULLENRICH_API_KEY,
                    unit: 'per_email',
                }, `FullEnrich reverse email lookup: ${matchCount} match(es) found`, {
                    bubbleName: 'fullenrich',
                    variableId: this.context?.variableId,
                    operationType: 'bubble_execution',
                });
            }
        }
        return result;
    }
    /**
     * Get current credit balance
     */
    async getCreditBalance(_params) {
        const response = await this.makeApiRequest('/account/credits', 'GET');
        return {
            operation: 'get_credit_balance',
            success: true,
            balance: response.balance,
            error: '',
        };
    }
    /**
     * Check if API key is valid
     */
    async checkApiKey(_params) {
        const response = await this.makeApiRequest('/account/keys/verify', 'GET');
        return {
            operation: 'check_api_key',
            success: true,
            workspace_id: response.workspace_id,
            error: '',
        };
    }
    /**
     * Choose the appropriate credential for FullEnrich
     */
    chooseCredential() {
        const { credentials } = this.params;
        if (!credentials || typeof credentials !== 'object') {
            return undefined;
        }
        return credentials[CredentialType.FULLENRICH_API_KEY];
    }
}
//# sourceMappingURL=fullenrich.js.map