/**
 * Iron Dome Cloud Sync
 *
 * Pulls custom injection patterns and central policy from ShieldCortex cloud.
 * Non-blocking, with disk cache fallback if cloud is unreachable.
 */
import { getCloudConfig, setCloudIronDomeCache as persistToConfig, getCloudIronDomeCache as readFromConfig } from './config.js';
import { setExternalPatterns } from '../defence/iron-dome/injection-scanner.js';
// ── State ──
let fetchInProgress = false;
let cachedData = null;
/**
 * Get the cached cloud Iron Dome data (in-memory or from disk).
 */
export function getCloudIronDomeCache() {
    if (cachedData)
        return cachedData;
    // Try loading from disk
    try {
        const raw = readFromConfig();
        if (raw) {
            cachedData = raw;
            return cachedData;
        }
    }
    catch { /* ignore */ }
    return null;
}
/**
 * Fetch custom patterns and policy from ShieldCortex cloud.
 * Non-blocking with 10s timeout. Falls back to disk cache on failure.
 */
export async function refreshCloudIronDome() {
    const config = getCloudConfig();
    if (!config.cloudEnabled || !config.cloudApiKey)
        return;
    if (fetchInProgress)
        return;
    fetchInProgress = true;
    try {
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 10_000);
        const headers = {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${config.cloudApiKey}`,
        };
        // Fetch patterns and policy in parallel
        const [patternsRes, policyRes] = await Promise.allSettled([
            fetch(`${config.cloudBaseUrl}/v1/iron-dome/patterns/sync`, {
                headers,
                signal: controller.signal,
            }),
            fetch(`${config.cloudBaseUrl}/v1/iron-dome/policies/sync`, {
                headers,
                signal: controller.signal,
            }),
        ]);
        clearTimeout(timeoutId);
        let patterns = [];
        let patternsUpdatedAt = null;
        let policy = null;
        let policyUpdatedAt = null;
        // Process patterns response
        if (patternsRes.status === 'fulfilled' && patternsRes.value.ok) {
            try {
                const data = await patternsRes.value.json();
                patterns = data.patterns ?? [];
                patternsUpdatedAt = data.updated_at;
            }
            catch { /* ignore parse errors */ }
        }
        // Process policy response
        if (policyRes.status === 'fulfilled' && policyRes.value.ok) {
            try {
                const data = await policyRes.value.json();
                policy = data.policy;
                policyUpdatedAt = data.updated_at;
            }
            catch { /* ignore parse errors */ }
        }
        // Update in-memory cache
        cachedData = {
            patterns,
            policy,
            patternsUpdatedAt,
            policyUpdatedAt,
            lastFetchedAt: new Date().toISOString(),
        };
        // Register external patterns with injection scanner
        if (patterns.length > 0) {
            setExternalPatterns(patterns);
        }
        // Persist to disk with HMAC integrity
        persistToConfig(cachedData);
    }
    catch {
        // Cloud unreachable — fall back to disk cache
        const diskCache = getCloudIronDomeCache();
        if (diskCache && diskCache.patterns.length > 0) {
            setExternalPatterns(diskCache.patterns);
        }
    }
    finally {
        fetchInProgress = false;
    }
}
/**
 * Apply cached cloud patterns on startup (before first cloud fetch).
 * Called once during initialisation.
 */
export function applyCachedCloudPatterns() {
    const cache = getCloudIronDomeCache();
    if (cache && cache.patterns.length > 0) {
        setExternalPatterns(cache.patterns);
    }
}
