"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TenantIntegrationsService = void 0; const common_1 = require("@nestjs/common"); const typeorm_1 = require("@nestjs/typeorm"); const typeorm_2 = require("typeorm"); const config_1 = require("@nestjs/config"); const tenant_integration_credential_entity_1 = require("../entities/tenant-integration-credential.entity"); const tenant_whatsapp_number_entity_1 = require("../entities/tenant-whatsapp-number.entity"); const tenant_entity_1 = require("../../auth/entities/tenant.entity"); let TenantIntegrationsService = class TenantIntegrationsService { constructor(credentialRepo, whatsappNumberRepo, tenantRepo, configService) { this.credentialRepo = credentialRepo; this.whatsappNumberRepo = whatsappNumberRepo; this.tenantRepo = tenantRepo; this.configService = configService; } async getWhatsAppCredentials(tenantId) { const tenantCredential = await this.credentialRepo.findOne({ where: { tenantId, integrationType: tenant_integration_credential_entity_1.IntegrationType.WHATSAPP, provider: tenant_integration_credential_entity_1.IntegrationProvider.META, isActive: true, }, }); if (tenantCredential && tenantCredential.credentials) { const creds = tenantCredential.credentials; if (creds.accessToken && creds.phoneNumberId) { return { accessToken: creds.accessToken, phoneNumberId: creds.phoneNumberId, businessAccountId: creds.businessAccountId, verifyToken: creds.verifyToken, isFromPlatform: false, tenantId, }; } } return this.getPlatformWhatsAppCredentials(); } getPlatformWhatsAppCredentials() { const accessToken = this.configService.get('WHATSAPP_ACCESS_TOKEN'); const phoneNumberId = this.configService.get('WHATSAPP_PHONE_NUMBER_ID'); if (!accessToken || !phoneNumberId) { throw new common_1.BadRequestException('WhatsApp platform credentials not configured'); } return { accessToken, phoneNumberId, businessAccountId: this.configService.get('WHATSAPP_BUSINESS_ACCOUNT_ID'), verifyToken: this.configService.get('WHATSAPP_VERIFY_TOKEN'), isFromPlatform: true, }; } async resolveTenantFromPhoneNumberId(phoneNumberId) { const whatsappNumber = await this.whatsappNumberRepo.findOne({ where: { phoneNumberId, isActive: true }, }); if (whatsappNumber) { return whatsappNumber.tenantId; } const platformPhoneNumberId = this.configService.get('WHATSAPP_PHONE_NUMBER_ID'); if (phoneNumberId === platformPhoneNumberId) { return null; } const credential = await this.credentialRepo.findOne({ where: { integrationType: tenant_integration_credential_entity_1.IntegrationType.WHATSAPP, isActive: true, }, }); if (credential) { const creds = credential.credentials; if (creds.phoneNumberId === phoneNumberId) { return credential.tenantId; } } return null; } async getLLMConfig(tenantId) { const tenant = await this.tenantRepo.findOne({ where: { id: tenantId } }); const preferredProvider = tenant?.preferredLlmProvider || 'openai'; const tenantCredential = await this.credentialRepo.findOne({ where: { tenantId, integrationType: tenant_integration_credential_entity_1.IntegrationType.LLM, isActive: true, }, }); if (tenantCredential && tenantCredential.credentials) { const creds = tenantCredential.credentials; const config = tenantCredential.config; if (creds.apiKey) { return { apiKey: creds.apiKey, provider: tenantCredential.provider, model: config.model || this.getDefaultModel(tenantCredential.provider), maxTokens: config.maxTokens || 1000, temperature: config.temperature || 0.7, baseUrl: config.baseUrl || this.getDefaultBaseUrl(tenantCredential.provider), systemPrompt: config.systemPrompt, isFromPlatform: false, tenantId, }; } } return this.getPlatformLLMConfig(); } getPlatformLLMConfig() { const apiKey = this.configService.get('OPENAI_API_KEY') || this.configService.get('LLM_API_KEY'); const provider = this.configService.get('LLM_PROVIDER', 'openai'); if (!apiKey) { throw new common_1.BadRequestException('LLM platform credentials not configured'); } return { apiKey, provider, model: this.configService.get('LLM_MODEL', 'gpt-4o-mini'), maxTokens: parseInt(this.configService.get('LLM_MAX_TOKENS', '1000')), temperature: parseFloat(this.configService.get('LLM_TEMPERATURE', '0.7')), baseUrl: this.configService.get('LLM_BASE_URL', 'https://api.openai.com/v1'), isFromPlatform: true, }; } getDefaultModel(provider) { const defaults = { [tenant_integration_credential_entity_1.IntegrationProvider.OPENAI]: 'gpt-4o-mini', [tenant_integration_credential_entity_1.IntegrationProvider.OPENROUTER]: 'anthropic/claude-3-haiku', [tenant_integration_credential_entity_1.IntegrationProvider.ANTHROPIC]: 'claude-3-haiku-20240307', [tenant_integration_credential_entity_1.IntegrationProvider.OLLAMA]: 'llama2', [tenant_integration_credential_entity_1.IntegrationProvider.AZURE_OPENAI]: 'gpt-4o-mini', }; return defaults[provider] || 'gpt-4o-mini'; } getDefaultBaseUrl(provider) { const defaults = { [tenant_integration_credential_entity_1.IntegrationProvider.OPENAI]: 'https://api.openai.com/v1', [tenant_integration_credential_entity_1.IntegrationProvider.OPENROUTER]: 'https://openrouter.ai/api/v1', [tenant_integration_credential_entity_1.IntegrationProvider.ANTHROPIC]: 'https://api.anthropic.com/v1', [tenant_integration_credential_entity_1.IntegrationProvider.OLLAMA]: 'http://localhost:11434/v1', }; return defaults[provider] || 'https://api.openai.com/v1'; } async upsertCredential(tenantId, integrationType, provider, credentials, config, userId) { let credential = await this.credentialRepo.findOne({ where: { tenantId, integrationType, provider }, }); if (credential) { credential.credentials = credentials; credential.config = config || credential.config; credential.updatedBy = userId; credential.isVerified = false; } else { credential = this.credentialRepo.create({ tenantId, integrationType, provider, credentials, config: config || {}, createdBy: userId, updatedBy: userId, }); } return this.credentialRepo.save(credential); } async getCredentials(tenantId) { return this.credentialRepo.find({ where: { tenantId }, order: { integrationType: 'ASC', provider: 'ASC' }, }); } async getCredential(tenantId, integrationType, provider) { return this.credentialRepo.findOne({ where: { tenantId, integrationType, provider }, }); } async deleteCredential(tenantId, integrationType, provider) { await this.credentialRepo.delete({ tenantId, integrationType, provider }); } async toggleCredential(tenantId, integrationType, provider, isActive) { const credential = await this.credentialRepo.findOne({ where: { tenantId, integrationType, provider }, }); if (!credential) { throw new common_1.NotFoundException('Credential not found'); } credential.isActive = isActive; return this.credentialRepo.save(credential); } async getIntegrationStatus(tenantId) { const credentials = await this.getCredentials(tenantId); const tenant = await this.tenantRepo.findOne({ where: { id: tenantId } }); const whatsappCred = credentials.find((c) => c.integrationType === tenant_integration_credential_entity_1.IntegrationType.WHATSAPP && c.isActive); const llmCred = credentials.find((c) => c.integrationType === tenant_integration_credential_entity_1.IntegrationType.LLM && c.isActive); const stripeCred = credentials.find((c) => c.integrationType === tenant_integration_credential_entity_1.IntegrationType.STRIPE && c.isActive); const mercadopagoCred = credentials.find((c) => c.integrationType === tenant_integration_credential_entity_1.IntegrationType.MERCADOPAGO && c.isActive); const clipCred = credentials.find((c) => c.integrationType === tenant_integration_credential_entity_1.IntegrationType.CLIP && c.isActive); return { whatsapp: { configured: !!whatsappCred, usesPlatformNumber: tenant?.usesPlatformNumber ?? true, provider: whatsappCred?.provider || 'meta', isVerified: whatsappCred?.isVerified ?? false, }, llm: { configured: !!llmCred, usesPlatformDefault: !llmCred, provider: llmCred?.provider || tenant?.preferredLlmProvider || 'openai', model: llmCred?.config?.model || 'gpt-4o-mini', isVerified: llmCred?.isVerified ?? false, }, payments: { stripe: { configured: !!stripeCred, isVerified: stripeCred?.isVerified ?? false, }, mercadopago: { configured: !!mercadopagoCred, isVerified: mercadopagoCred?.isVerified ?? false, }, clip: { configured: !!clipCred, isVerified: clipCred?.isVerified ?? false, }, }, }; } async registerWhatsAppNumber(tenantId, phoneNumberId, phoneNumber, displayName, isPlatformNumber = false) { let mapping = await this.whatsappNumberRepo.findOne({ where: { phoneNumberId }, }); if (mapping) { mapping.tenantId = tenantId; mapping.phoneNumber = phoneNumber || mapping.phoneNumber; mapping.displayName = displayName || mapping.displayName; mapping.isPlatformNumber = isPlatformNumber; } else { mapping = this.whatsappNumberRepo.create({ tenantId, phoneNumberId, phoneNumber, displayName, isPlatformNumber, }); } return this.whatsappNumberRepo.save(mapping); } }; exports.TenantIntegrationsService = TenantIntegrationsService; exports.TenantIntegrationsService = TenantIntegrationsService = __decorate([ (0, common_1.Injectable)(), __param(0, (0, typeorm_1.InjectRepository)(tenant_integration_credential_entity_1.TenantIntegrationCredential)), __param(1, (0, typeorm_1.InjectRepository)(tenant_whatsapp_number_entity_1.TenantWhatsAppNumber)), __param(2, (0, typeorm_1.InjectRepository)(tenant_entity_1.Tenant)), __metadata("design:paramtypes", [typeorm_2.Repository, typeorm_2.Repository, typeorm_2.Repository, config_1.ConfigService]) ], TenantIntegrationsService); //# sourceMappingURL=tenant-integrations.service.js.map