/**
 * Alert Management
 * Trust score degradation, breach notifications, compliance expiration, and SIEM integration
 */
// ============================================================================
// Alert Manager Service
// ============================================================================
export class AlertManager {
    config;
    recentAlerts = new Map();
    constructor(config) {
        this.config = config;
    }
    // ============================================================================
    // Alert Creation
    // ============================================================================
    async createAlert(input) {
        // Check for duplicates
        const dedupeKey = this.generateDedupeKey(input);
        const existingAlert = this.recentAlerts.get(dedupeKey);
        if (existingAlert && this.isWithinDedupeWindow(existingAlert)) {
            // Update existing alert instead of creating new
            return this.updateAlert(existingAlert.id, {
                relatedEvents: [...existingAlert.relatedEvents, ...(input.relatedEvents || [])],
            });
        }
        const alert = {
            id: this.generateAlertId(),
            vendorId: input.vendorId,
            type: input.type,
            severity: input.severity,
            title: input.title,
            description: input.description,
            source: input.source,
            createdAt: new Date(),
            status: 'open',
            relatedEvents: input.relatedEvents || [],
            actions: this.generateAlertActions(input),
            metadata: input.metadata || {},
        };
        await this.config.storage.saveAlert(alert);
        this.recentAlerts.set(dedupeKey, alert);
        // Send notifications
        await this.sendNotifications(alert);
        // Send to SIEM
        if (this.config.siemIntegration) {
            await this.sendToSIEM(alert);
        }
        // Check escalation policies
        await this.checkEscalationPolicies(alert);
        return alert;
    }
    async createAlertFromHealthEvent(event, vendor) {
        const alertType = this.mapHealthEventToAlertType(event.type);
        if (!alertType)
            return null;
        const severity = this.mapEventSeverityToAlertSeverity(event.severity);
        return this.createAlert({
            vendorId: event.vendorId,
            type: alertType,
            severity,
            title: event.title,
            description: event.description,
            source: event.source,
            relatedEvents: [event.id],
            metadata: {
                eventType: event.type,
                vendorName: vendor.name,
                vendorTier: vendor.tier,
                ...event.metadata,
            },
        });
    }
    async createTrustScoreDegradationAlert(vendorId, vendor, previousScore, currentScore) {
        const scoreDrop = previousScore.score - currentScore.score;
        const severity = this.calculateDegradationSeverity(scoreDrop, vendor.tier);
        return this.createAlert({
            vendorId,
            type: 'trust_score_degradation',
            severity,
            title: `Trust score degradation detected for ${vendor.name}`,
            description: `Trust score dropped from ${previousScore.score} (${previousScore.grade}) to ${currentScore.score} (${currentScore.grade})`,
            source: 'trust_oracle',
            metadata: {
                vendorName: vendor.name,
                vendorTier: vendor.tier,
                previousScore: previousScore.score,
                previousGrade: previousScore.grade,
                currentScore: currentScore.score,
                currentGrade: currentScore.grade,
                scoreDrop,
                affectedFactors: currentScore.factors.filter(f => {
                    const prevFactor = previousScore.factors.find(pf => pf.category === f.category);
                    return prevFactor && prevFactor.score - f.score > 5;
                }),
            },
        });
    }
    async createComplianceExpirationAlert(vendorId, vendor, certification, daysUntilExpiration) {
        const severity = daysUntilExpiration <= 7 ? 'critical' :
            daysUntilExpiration <= 30 ? 'error' :
                daysUntilExpiration <= 60 ? 'warning' : 'info';
        return this.createAlert({
            vendorId,
            type: 'compliance_expiration',
            severity,
            title: `${certification.framework} certification expiring for ${vendor.name}`,
            description: `${certification.framework} certification expires in ${daysUntilExpiration} days on ${certification.expirationDate.toISOString().split('T')[0]}`,
            source: 'trust_oracle',
            metadata: {
                vendorName: vendor.name,
                vendorTier: vendor.tier,
                certificationId: certification.id,
                framework: certification.framework,
                expirationDate: certification.expirationDate,
                daysUntilExpiration,
                certificationBody: certification.certificationBody,
            },
        });
    }
    async createContractExpirationAlert(vendorId, vendor, contract, daysUntilExpiration) {
        const severity = daysUntilExpiration <= 7 ? 'critical' :
            daysUntilExpiration <= 30 ? 'error' :
                daysUntilExpiration <= 60 ? 'warning' : 'info';
        return this.createAlert({
            vendorId,
            type: 'contract_expiration',
            severity,
            title: `Contract expiring for ${vendor.name}`,
            description: `${contract.type} contract expires in ${daysUntilExpiration} days on ${contract.endDate.toISOString().split('T')[0]}`,
            source: 'trust_oracle',
            metadata: {
                vendorName: vendor.name,
                vendorTier: vendor.tier,
                contractId: contract.id,
                contractType: contract.type,
                endDate: contract.endDate,
                daysUntilExpiration,
                autoRenewal: contract.autoRenewal,
                contractValue: contract.value,
            },
        });
    }
    async createBreachAlert(vendorId, vendor, breach) {
        const severity = this.calculateBreachSeverity(breach);
        return this.createAlert({
            vendorId,
            type: 'breach_notification',
            severity,
            title: `Data breach reported for ${vendor.name}`,
            description: breach.description,
            source: breach.source,
            metadata: {
                vendorName: vendor.name,
                vendorTier: vendor.tier,
                breachDate: breach.breachDate,
                disclosureDate: breach.disclosureDate,
                recordsAffected: breach.recordsAffected,
                dataTypes: breach.dataTypes,
                breachId: breach.breachId,
            },
        });
    }
    // ============================================================================
    // Alert Management
    // ============================================================================
    async getAlert(alertId) {
        const alert = await this.config.storage.getAlert(alertId);
        if (!alert) {
            throw new AlertError('ALERT_NOT_FOUND', `Alert ${alertId} not found`);
        }
        return alert;
    }
    async updateAlert(alertId, updates) {
        const alert = await this.getAlert(alertId);
        const updatedAlert = {
            ...alert,
            ...updates,
            id: alert.id, // Prevent ID modification
            vendorId: alert.vendorId, // Prevent vendor modification
            createdAt: alert.createdAt, // Prevent creation date modification
        };
        await this.config.storage.saveAlert(updatedAlert);
        return updatedAlert;
    }
    async acknowledgeAlert(alertId, acknowledgedBy) {
        return this.updateAlert(alertId, {
            status: 'acknowledged',
            acknowledgedAt: new Date(),
            assignee: acknowledgedBy,
        });
    }
    async resolveAlert(alertId, resolution) {
        const alert = await this.updateAlert(alertId, {
            status: 'resolved',
            resolvedAt: new Date(),
            metadata: {
                ...((await this.getAlert(alertId)).metadata),
                resolution,
            },
        });
        // Remove from deduplication cache
        const dedupeKey = this.generateDedupeKey({
            vendorId: alert.vendorId,
            type: alert.type,
            title: alert.title,
        });
        this.recentAlerts.delete(dedupeKey);
        return alert;
    }
    async suppressAlert(alertId, reason, duration) {
        return this.updateAlert(alertId, {
            status: 'suppressed',
            metadata: {
                ...((await this.getAlert(alertId)).metadata),
                suppressionReason: reason,
                suppressedUntil: new Date(Date.now() + duration),
            },
        });
    }
    async assignAlert(alertId, assignee) {
        return this.updateAlert(alertId, {
            assignee,
            status: 'investigating',
        });
    }
    async addComment(alertId, comment) {
        await this.config.storage.addAlertComment(alertId, comment);
    }
    // ============================================================================
    // Alert Queries
    // ============================================================================
    async listAlerts(options) {
        return this.config.storage.listAlerts(options);
    }
    async getVendorAlerts(vendorId, options = {}) {
        const result = await this.config.storage.listAlerts({
            ...options,
            vendorId,
        });
        return result.data;
    }
    async getOpenAlerts(options = {}) {
        const result = await this.config.storage.listAlerts({
            ...options,
            statuses: ['open', 'acknowledged', 'investigating'],
        });
        return result.data;
    }
    async getAlertsByType(type, options = {}) {
        const result = await this.config.storage.listAlerts({
            ...options,
            types: [type],
        });
        return result.data;
    }
    async getAlertStats(vendorId) {
        return this.config.storage.getAlertStats(vendorId);
    }
    // ============================================================================
    // Bulk Operations
    // ============================================================================
    async bulkAcknowledge(alertIds, acknowledgedBy) {
        const results = [];
        for (const alertId of alertIds) {
            try {
                const alert = await this.acknowledgeAlert(alertId, acknowledgedBy);
                results.push(alert);
            }
            catch (error) {
                console.error(`Failed to acknowledge alert ${alertId}:`, error);
            }
        }
        return results;
    }
    async bulkResolve(alertIds, resolution) {
        const results = [];
        for (const alertId of alertIds) {
            try {
                const alert = await this.resolveAlert(alertId, resolution);
                results.push(alert);
            }
            catch (error) {
                console.error(`Failed to resolve alert ${alertId}:`, error);
            }
        }
        return results;
    }
    async autoResolveStaleAlerts(maxAgeHours) {
        if (!this.config.autoResolveEnabled)
            return 0;
        const staleAlerts = await this.config.storage.getStaleAlerts(maxAgeHours);
        let resolvedCount = 0;
        for (const alert of staleAlerts) {
            try {
                await this.resolveAlert(alert.id, {
                    type: 'auto_resolved',
                    reason: `Auto-resolved after ${maxAgeHours} hours of inactivity`,
                    resolvedBy: 'system',
                });
                resolvedCount++;
            }
            catch (error) {
                console.error(`Failed to auto-resolve alert ${alert.id}:`, error);
            }
        }
        return resolvedCount;
    }
    // ============================================================================
    // Notification Management
    // ============================================================================
    async sendNotifications(alert) {
        const channels = this.config.notificationChannels.filter(c => this.shouldNotifyChannel(c, alert));
        const notifications = channels.map(channel => this.sendNotificationToChannel(channel, alert).catch(error => {
            console.error(`Failed to send notification to ${channel.type}:`, error);
        }));
        await Promise.all(notifications);
    }
    shouldNotifyChannel(channel, alert) {
        // Check severity threshold
        const severityOrder = { info: 0, warning: 1, error: 2, critical: 3 };
        if (severityOrder[alert.severity] < severityOrder[channel.minSeverity || 'info']) {
            return false;
        }
        // Check alert type filter
        if (channel.alertTypes && !channel.alertTypes.includes(alert.type)) {
            return false;
        }
        return channel.enabled;
    }
    async sendNotificationToChannel(channel, alert) {
        const payload = this.formatNotificationPayload(channel, alert);
        switch (channel.type) {
            case 'email':
                await this.sendEmailNotification(channel, payload);
                break;
            case 'slack':
                await this.sendSlackNotification(channel, payload);
                break;
            case 'teams':
                await this.sendTeamsNotification(channel, payload);
                break;
            case 'pagerduty':
                await this.sendPagerDutyNotification(channel, payload);
                break;
            case 'webhook':
                await this.sendWebhookNotification(channel, payload);
                break;
        }
    }
    formatNotificationPayload(channel, alert) {
        return {
            title: alert.title,
            description: alert.description,
            severity: alert.severity,
            type: alert.type,
            vendorId: alert.vendorId,
            alertId: alert.id,
            createdAt: alert.createdAt,
            source: alert.source,
            actions: alert.actions,
            metadata: alert.metadata,
        };
    }
    async sendEmailNotification(channel, payload) {
        // Email implementation
        console.log('Sending email notification:', payload);
    }
    async sendSlackNotification(channel, payload) {
        const webhookUrl = channel.config.webhookUrl;
        if (!webhookUrl)
            return;
        const slackPayload = {
            text: payload.title,
            attachments: [{
                    color: this.getSeverityColor(payload.severity),
                    title: payload.title,
                    text: payload.description,
                    fields: [
                        { title: 'Severity', value: payload.severity, short: true },
                        { title: 'Type', value: payload.type, short: true },
                        { title: 'Vendor', value: payload.vendorId, short: true },
                        { title: 'Source', value: payload.source, short: true },
                    ],
                    footer: 'Trust Oracle',
                    ts: Math.floor(payload.createdAt.getTime() / 1000),
                }],
        };
        await fetch(webhookUrl, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(slackPayload),
        });
    }
    async sendTeamsNotification(channel, payload) {
        const webhookUrl = channel.config.webhookUrl;
        if (!webhookUrl)
            return;
        const teamsPayload = {
            '@type': 'MessageCard',
            '@context': 'http://schema.org/extensions',
            themeColor: this.getSeverityColor(payload.severity).replace('#', ''),
            summary: payload.title,
            sections: [{
                    activityTitle: payload.title,
                    activitySubtitle: `Severity: ${payload.severity}`,
                    facts: [
                        { name: 'Type', value: payload.type },
                        { name: 'Vendor', value: payload.vendorId },
                        { name: 'Source', value: payload.source },
                    ],
                    text: payload.description,
                }],
        };
        await fetch(webhookUrl, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(teamsPayload),
        });
    }
    async sendPagerDutyNotification(channel, payload) {
        const routingKey = channel.config.routingKey;
        if (!routingKey)
            return;
        const pdPayload = {
            routing_key: routingKey,
            event_action: 'trigger',
            dedup_key: payload.alertId,
            payload: {
                summary: payload.title,
                severity: this.mapSeverityToPagerDuty(payload.severity),
                source: 'Trust Oracle',
                custom_details: {
                    description: payload.description,
                    vendor_id: payload.vendorId,
                    alert_type: payload.type,
                    ...payload.metadata,
                },
            },
        };
        await fetch('https://events.pagerduty.com/v2/enqueue', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(pdPayload),
        });
    }
    async sendWebhookNotification(channel, payload) {
        const webhookUrl = channel.config.url;
        if (!webhookUrl)
            return;
        const headers = {
            'Content-Type': 'application/json',
        };
        if (channel.config.authHeader) {
            headers['Authorization'] = channel.config.authHeader;
        }
        await fetch(webhookUrl, {
            method: 'POST',
            headers,
            body: JSON.stringify(payload),
        });
    }
    // ============================================================================
    // SIEM Integration
    // ============================================================================
    async sendToSIEM(alert) {
        const siem = this.config.siemIntegration;
        if (!siem)
            return;
        const siemEvent = this.formatSIEMEvent(alert);
        try {
            await siem.sendEvent(siemEvent);
        }
        catch (error) {
            console.error('Failed to send event to SIEM:', error);
        }
    }
    formatSIEMEvent(alert) {
        return {
            timestamp: alert.createdAt,
            eventType: 'security_alert',
            severity: this.mapSeverityToSIEM(alert.severity),
            source: 'trust_oracle',
            category: 'vendor_risk',
            subcategory: alert.type,
            description: alert.title,
            details: {
                alertId: alert.id,
                vendorId: alert.vendorId,
                description: alert.description,
                source: alert.source,
                status: alert.status,
                ...alert.metadata,
            },
            indicators: this.extractIndicators(alert),
        };
    }
    mapSeverityToSIEM(severity) {
        const mapping = {
            info: 1,
            warning: 3,
            error: 5,
            critical: 8,
        };
        return mapping[severity];
    }
    extractIndicators(alert) {
        const indicators = [];
        // Extract vendor domain as indicator
        if (alert.metadata.domain) {
            indicators.push({
                type: 'domain',
                value: alert.metadata.domain,
                confidence: 'high',
            });
        }
        return indicators;
    }
    // ============================================================================
    // Escalation
    // ============================================================================
    async checkEscalationPolicies(alert) {
        for (const policy of this.config.escalationPolicies) {
            if (this.matchesEscalationConditions(alert, policy.conditions)) {
                await this.executeEscalationActions(alert, policy.actions);
            }
        }
    }
    matchesEscalationConditions(alert, conditions) {
        for (const condition of conditions) {
            if (!this.matchesCondition(alert, condition)) {
                return false;
            }
        }
        return true;
    }
    matchesCondition(alert, condition) {
        let fieldValue;
        switch (condition.field) {
            case 'severity':
                fieldValue = alert.severity;
                break;
            case 'type':
                fieldValue = alert.type;
                break;
            case 'age':
                fieldValue = Date.now() - alert.createdAt.getTime();
                break;
            case 'vendorTier':
                fieldValue = alert.metadata.vendorTier;
                break;
            default:
                return false;
        }
        switch (condition.operator) {
            case 'eq':
                return fieldValue === condition.value;
            case 'neq':
                return fieldValue !== condition.value;
            case 'gt':
                return fieldValue > condition.value;
            case 'lt':
                return fieldValue < condition.value;
            case 'in':
                return condition.value.includes(fieldValue);
            default:
                return false;
        }
    }
    async executeEscalationActions(alert, actions) {
        for (const action of actions) {
            try {
                switch (action.type) {
                    case 'notify':
                        await this.escalationNotify(alert, action.config);
                        break;
                    case 'assign':
                        await this.assignAlert(alert.id, action.config.assignee);
                        break;
                    case 'change_severity':
                        await this.updateAlert(alert.id, {
                            severity: action.config.newSeverity,
                        });
                        break;
                    case 'create_incident':
                        await this.createIncident(alert, action.config);
                        break;
                }
            }
            catch (error) {
                console.error(`Failed to execute escalation action ${action.type}:`, error);
            }
        }
    }
    async escalationNotify(alert, config) {
        // Send escalation notifications
        const recipients = config.recipients;
        console.log(`Escalating alert ${alert.id} to:`, recipients);
    }
    async createIncident(alert, config) {
        // Create incident in incident management system
        console.log(`Creating incident for alert ${alert.id}`);
    }
    // ============================================================================
    // Helper Methods
    // ============================================================================
    generateAlertId() {
        return `alert_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
    }
    generateDedupeKey(input) {
        return `${input.vendorId}:${input.type}:${input.title}`;
    }
    isWithinDedupeWindow(alert) {
        return Date.now() - alert.createdAt.getTime() < this.config.deduplicationWindow;
    }
    generateAlertActions(input) {
        const actions = [
            {
                type: 'link',
                label: 'View Vendor Details',
                target: `/vendors/${input.vendorId}`,
            },
        ];
        // Add type-specific actions
        switch (input.type) {
            case 'trust_score_degradation':
                actions.push({
                    type: 'link',
                    label: 'View Trust Score History',
                    target: `/vendors/${input.vendorId}/trust-history`,
                });
                break;
            case 'compliance_expiration':
                actions.push({
                    type: 'api_call',
                    label: 'Request Renewal',
                    target: `/api/vendors/${input.vendorId}/certifications/request-renewal`,
                    parameters: { certificationId: input.metadata?.certificationId },
                });
                break;
            case 'breach_notification':
                actions.push({
                    type: 'workflow',
                    label: 'Start Incident Response',
                    target: 'incident_response_workflow',
                    parameters: { vendorId: input.vendorId, breachId: input.metadata?.breachId },
                });
                break;
        }
        return actions;
    }
    mapHealthEventToAlertType(eventType) {
        const mapping = {
            security_incident: 'security_incident',
            breach_disclosure: 'breach_notification',
            certificate_expiring: 'certificate_expiration',
            certificate_expired: 'certificate_expiration',
            compliance_gap: 'compliance_expiration',
            score_degradation: 'trust_score_degradation',
            sla_breach: 'sla_violation',
            dark_web_mention: 'dark_web_exposure',
            sanctions_match: 'sanctions_match',
        };
        return mapping[eventType] || null;
    }
    mapEventSeverityToAlertSeverity(eventSeverity) {
        return eventSeverity;
    }
    calculateDegradationSeverity(scoreDrop, vendorTier) {
        const tierMultiplier = vendorTier === 'critical' ? 2 : vendorTier === 'high' ? 1.5 : 1;
        const adjustedDrop = scoreDrop * tierMultiplier;
        if (adjustedDrop >= 30)
            return 'critical';
        if (adjustedDrop >= 20)
            return 'error';
        if (adjustedDrop >= 10)
            return 'warning';
        return 'info';
    }
    calculateBreachSeverity(breach) {
        const sensitiveTypes = ['passwords', 'financial', 'health', 'ssn', 'credit_card'];
        const hasSensitiveData = breach.dataTypes.some(t => sensitiveTypes.some(s => t.toLowerCase().includes(s)));
        if (hasSensitiveData && (breach.recordsAffected || 0) > 100000)
            return 'critical';
        if (hasSensitiveData || (breach.recordsAffected || 0) > 1000000)
            return 'error';
        if ((breach.recordsAffected || 0) > 10000)
            return 'warning';
        return 'info';
    }
    getSeverityColor(severity) {
        const colors = {
            info: '#2196F3',
            warning: '#FF9800',
            error: '#F44336',
            critical: '#9C27B0',
        };
        return colors[severity];
    }
    mapSeverityToPagerDuty(severity) {
        const mapping = {
            info: 'info',
            warning: 'warning',
            error: 'error',
            critical: 'critical',
        };
        return mapping[severity];
    }
}
// ============================================================================
// Error Class
// ============================================================================
export class AlertError extends Error {
    code;
    constructor(code, message) {
        super(message);
        this.code = code;
        this.name = 'AlertError';
    }
}
// ============================================================================
// Factory Function
// ============================================================================
export function createAlertManager(config) {
    return new AlertManager(config);
}
export function getDefaultEscalationPolicies() {
    return [
        {
            name: 'Critical Vendor Alert',
            conditions: [
                { field: 'severity', operator: 'eq', value: 'critical' },
                { field: 'vendorTier', operator: 'in', value: ['critical', 'high'] },
            ],
            actions: [
                { type: 'notify', config: { recipients: ['security-team@company.com'] } },
                { type: 'create_incident', config: { priority: 'P1' } },
            ],
        },
        {
            name: 'Aged Alert Escalation',
            conditions: [
                { field: 'age', operator: 'gt', value: 24 * 60 * 60 * 1000 }, // 24 hours
                { field: 'severity', operator: 'in', value: ['error', 'critical'] },
            ],
            actions: [
                { type: 'notify', config: { recipients: ['security-manager@company.com'] } },
                { type: 'change_severity', config: { newSeverity: 'critical' } },
            ],
        },
        {
            name: 'Breach Notification',
            conditions: [
                { field: 'type', operator: 'eq', value: 'breach_notification' },
            ],
            actions: [
                { type: 'notify', config: { recipients: ['legal@company.com', 'security@company.com'] } },
                { type: 'create_incident', config: { priority: 'P1', template: 'breach_response' } },
            ],
        },
    ];
}
//# sourceMappingURL=alerts.js.map