import { apiFetchJSON } from '@/utils/apiClient'; export interface EmailProvider { id?: string; name: string; smtpHost: string; smtpPort: number; tls: boolean; startTLS: boolean; authRequired: boolean; instructions: string; server?: string; port?: number; security?: 'none' | 'tls' | 'starttls'; } export interface WebhookTemplate { id?: string; service: string; name: string; urlPattern: string; method: string; headers: Record; payloadTemplate: string; instructions: string; description?: string; template?: { url?: string; method?: string; headers?: Record; body?: string; }; } export interface EmailConfig { enabled: boolean; provider: string; server: string; port: number; username: string; password?: string; from: string; to: string[]; tls: boolean; startTLS: boolean; } export interface Webhook { id: string; name: string; url: string; method: string; headers: Record; template?: string; enabled: boolean; service?: string; // Added to support Discord, Slack, etc. customFields?: Record; } export interface AppriseConfig { enabled: boolean; mode?: 'cli' | 'http'; targets?: string[]; cliPath?: string; timeoutSeconds?: number; serverUrl?: string; configKey?: string; apiKey?: string; apiKeyHeader?: string; skipTlsVerify?: boolean; } export interface NotificationTestRequest { type: 'email' | 'webhook' | 'apprise'; config?: Record | AppriseConfig; // Backend expects different format than frontend types webhookId?: string; } export class NotificationsAPI { private static baseUrl = '/api/notifications'; static async getAppriseConfig(): Promise { return apiFetchJSON(`${this.baseUrl}/apprise`); } static async updateAppriseConfig(config: AppriseConfig): Promise { return apiFetchJSON(`${this.baseUrl}/apprise`, { method: 'PUT', body: JSON.stringify(config), }); } // Email configuration static async getEmailConfig(): Promise { const backendConfig = await apiFetchJSON>(`${this.baseUrl}/email`); // Backend already returns fields with correct names (server, port) return { enabled: (backendConfig.enabled as boolean) || false, provider: (backendConfig.provider as string) || '', server: (backendConfig.server as string) || '', port: (backendConfig.port as number) || 587, username: (backendConfig.username as string) || '', password: (backendConfig.password as string) || '', from: (backendConfig.from as string) || '', to: (backendConfig.to as string[]) || [], tls: (backendConfig.tls as boolean) || false, startTLS: (backendConfig.startTLS as boolean) || false, }; } static async updateEmailConfig(config: EmailConfig): Promise<{ success: boolean }> { // Backend expects fields with these names (server, port) const backendConfig = { enabled: config.enabled, server: config.server, port: config.port, username: config.username, password: config.password, from: config.from, to: config.to, tls: config.tls || false, startTLS: config.startTLS || false, provider: config.provider || '', }; return apiFetchJSON(`${this.baseUrl}/email`, { method: 'PUT', body: JSON.stringify(backendConfig), }); } // Webhook management static async getWebhooks(): Promise { const data = await apiFetchJSON(`${this.baseUrl}/webhooks`); return Array.isArray(data) ? data : []; } static async createWebhook(webhook: Omit): Promise { return apiFetchJSON(`${this.baseUrl}/webhooks`, { method: 'POST', body: JSON.stringify(webhook), }); } static async updateWebhook(id: string, webhook: Partial): Promise { return apiFetchJSON(`${this.baseUrl}/webhooks/${id}`, { method: 'PUT', body: JSON.stringify(webhook), }); } static async deleteWebhook(id: string): Promise<{ success: boolean }> { return apiFetchJSON(`${this.baseUrl}/webhooks/${id}`, { method: 'DELETE', }); } // Templates and providers static async getEmailProviders(): Promise { return apiFetchJSON(`${this.baseUrl}/email-providers`); } static async getWebhookTemplates(): Promise { return apiFetchJSON(`${this.baseUrl}/webhook-templates`); } // Testing static async testNotification( request: NotificationTestRequest, ): Promise<{ success: boolean; message?: string }> { const body: { method: string; config?: Record | AppriseConfig; webhookId?: string } = { method: request.type, }; // Include config if provided for testing without saving if (request.config) { body.config = request.config; } // Include webhookId for webhook testing if (request.webhookId) { body.webhookId = request.webhookId; } return apiFetchJSON(`${this.baseUrl}/test`, { method: 'POST', body: JSON.stringify(body), }); } static async testWebhook( webhook: Omit, ): Promise<{ success: boolean; message?: string }> { return apiFetchJSON(`${this.baseUrl}/webhooks/test`, { method: 'POST', body: JSON.stringify(webhook), }); } // Queue and DLQ management static async getQueueStats(): Promise> { return apiFetchJSON(`${this.baseUrl}/queue/stats`); } static async getDLQ(limit = 100): Promise { return apiFetchJSON(`${this.baseUrl}/dlq?limit=${limit}`); } static async retryDLQItem(id: string): Promise<{ success: boolean }> { return apiFetchJSON(`${this.baseUrl}/dlq/retry`, { method: 'POST', body: JSON.stringify({ id }), }); } static async deleteDLQItem(id: string): Promise<{ success: boolean }> { return apiFetchJSON(`${this.baseUrl}/dlq/delete`, { method: 'POST', body: JSON.stringify({ id }), }); } static async getNotificationHealth(): Promise<{ queue?: { healthy: boolean; pending: number; sending: number; sent: number; failed: number; dlq: number; }; email: { enabled: boolean; configured: boolean; }; webhooks: { total: number; enabled: number; }; encryption: { enabled: boolean; }; healthy: boolean; }> { return apiFetchJSON(`${this.baseUrl}/health`); } static async getWebhookHistory(): Promise { return apiFetchJSON(`${this.baseUrl}/webhook-history`); } }