import { Injectable } from '@nestjs/common'; import { WhatsappConfigRepository } from './repositories/whatsapp-config.repository'; interface WhatsappConfig { access_token: string | null; phone_number_id: string | null; api_version: string; webhook_token: string | null; } @Injectable() export class WhatsappConfigService { private _cache: { config: WhatsappConfig; expiresAt: number } | null = null; private readonly CACHE_TTL_MS = 60_000; constructor(private readonly repo: WhatsappConfigRepository) {} async getConfig(): Promise { if (this._cache && Date.now() < this._cache.expiresAt) { return this._cache.config; } const row = await this.repo.find(); const config: WhatsappConfig = { access_token: row?.access_token || process.env.META_ACCESS_TOKEN || null, phone_number_id: row?.phone_number_id || process.env.META_PHONE_NUMBER_ID || null, api_version: row?.api_version || process.env.META_API_VERSION || 'v25.0', webhook_token: row?.webhook_token || process.env.META_WEBHOOK_TOKEN || null, }; this._cache = { config, expiresAt: Date.now() + this.CACHE_TTL_MS }; return config; } async getPublicConfig() { const row = await this.repo.find(); const effectiveToken = row?.access_token || process.env.META_ACCESS_TOKEN; const effectivePhoneId = row?.phone_number_id || process.env.META_PHONE_NUMBER_ID; return { phone_number_id: effectivePhoneId || null, api_version: row?.api_version || process.env.META_API_VERSION || 'v25.0', webhook_token: row?.webhook_token || process.env.META_WEBHOOK_TOKEN || null, is_configured: !!(effectiveToken && effectivePhoneId), has_token: !!effectiveToken, token_source: row?.access_token ? 'database' : effectiveToken ? 'env' : null, updated_at: row?.updated_at || null, }; } async saveConfig( dto: { access_token?: string; phone_number_id?: string; api_version?: string; webhook_token?: string }, userId?: number, ) { this._cache = null; await this.repo.update({ access_token: dto.access_token || null, phone_number_id: dto.phone_number_id || null, api_version: dto.api_version || null, webhook_token: dto.webhook_token || null, updated_by: userId, }); return this.getPublicConfig(); } async validateCredentials(token: string, phoneNumberId: string, apiVersion = 'v25.0') { const url = `https://graph.facebook.com/${apiVersion}/${phoneNumberId}?access_token=${token}&fields=display_phone_number,verified_name,quality_rating`; try { const response = await fetch(url); const data = (await response.json()) as any; if (!response.ok) { return { valid: false, error: data?.error?.message || 'Credenciais inválidas', code: data?.error?.code, }; } return { valid: true, phone_number: data.display_phone_number, verified_name: data.verified_name, quality_rating: data.quality_rating, }; } catch (err: any) { const msg = err?.message || String(err); console.error('[WhatsappConfig] validateCredentials falhou:', msg); return { valid: false, error: `Erro de conexão com a Meta API: ${msg}` }; } } }