/**
 * Geographic Collector
 * Phase 5: Best-effort geographic intelligence
 */
import { getLatencyClass } from '../core/constants.js';
const ALLOW_GEO_LOOKUP = process.env.ALLOW_GEO_LOOKUP === '1';
/**
 * Get origin from environment or local IP
 */
async function getOrigin() {
    // Priority 1: Manual env override
    const manualLabel = process.env.FOURRUNR_ORIGIN_LABEL;
    const manualLat = process.env.FOURRUNR_ORIGIN_LAT;
    const manualLon = process.env.FOURRUNR_ORIGIN_LON;
    if (manualLabel) {
        return {
            label: manualLabel,
            region: process.env.FOURRUNR_ORIGIN_REGION || "UNKNOWN",
            latLon: (manualLat && manualLon) ? {
                lat: parseFloat(manualLat),
                lon: parseFloat(manualLon),
            } : undefined,
            source: "MANUAL",
        };
    }
    // Priority 2: Local IP geo lookup (only if enabled)
    if (process.env.ALLOW_GEO_LOOKUP === '1') {
        try {
            // In a real implementation, this would call a geo IP service
            // For v1, we'll return UNKNOWN to be privacy-safe
            // This is a placeholder for future implementation
            return {
                label: "UNKNOWN",
                region: "UNKNOWN",
                source: "NONE",
            };
        }
        catch {
            return {
                label: "UNKNOWN",
                region: "UNKNOWN",
                source: "NONE",
            };
        }
    }
    // Default: UNKNOWN
    return {
        label: "UNKNOWN",
        region: "UNKNOWN",
        source: "NONE",
    };
}
/**
 * Get gateway region from AWS metadata or env
 */
async function getGatewayRegion(appState) {
    // Priority 1: Env override
    const envRegion = process.env.FOURRUNR_AWS_REGION;
    if (envRegion) {
        return {
            region: envRegion,
            source: "ENV",
        };
    }
    // Priority 2: AWS instance metadata (only if on EC2)
    if (process.env.ALLOW_AWS_META === '1') {
        try {
            // In a real implementation, this would query IMDSv2
            // For v1, we'll return UNKNOWN
            // This is a placeholder for future implementation
            return {
                region: "UNKNOWN",
                source: "NONE",
            };
        }
        catch {
            return {
                region: "UNKNOWN",
                source: "NONE",
            };
        }
    }
    // Try to derive from gateway URL
    if (appState.gatewayUrl) {
        const url = appState.gatewayUrl.toLowerCase();
        // Simple pattern matching for AWS regions in URLs
        const regionMatch = url.match(/(us|eu|ap|sa|ca|cn)-(east|west|central|north|south)-\d/);
        if (regionMatch) {
            return {
                region: regionMatch[0],
                source: "ENV",
            };
        }
    }
    return {
        region: "UNKNOWN",
        source: "NONE",
    };
}
/**
 * Get database region
 */
async function getDbRegion(appState) {
    // Priority 1: Env override
    const envRegion = process.env.FOURRUNR_DB_REGION;
    if (envRegion) {
        return envRegion;
    }
    // Priority 2: Derive from connection string (if available)
    // This would parse the connection string for region info
    // For v1, return UNKNOWN
    return "UNKNOWN";
}
/**
 * Ping gateway endpoint (if configured)
 * Returns latency in ms or UNKNOWN
 */
async function pingGateway(appState) {
    if (!appState.gatewayUrl || !appState.gatewayConnected) {
        return "UNKNOWN";
    }
    // In a real implementation, this would perform an actual ping/HTTP request
    // For v1, we'll use the existing latency from network collector if available
    // This is a placeholder for future implementation
    return "UNKNOWN";
}
/**
 * Convert AWS region to approximate lat/lon
 * This is a best-effort mapping for visualization
 */
function regionToLatLon(region) {
    // Approximate region centers (best-effort)
    const regionMap = {
        'us-east-1': { lat: 33.7490, lon: -84.3880 }, // Atlanta
        'us-east-2': { lat: 40.7128, lon: -74.0060 }, // New York
        'us-west-1': { lat: 37.7749, lon: -122.4194 }, // San Francisco
        'us-west-2': { lat: 45.5152, lon: -122.6784 }, // Portland
        'eu-west-1': { lat: 53.3498, lon: -6.2603 }, // Dublin
        'eu-central-1': { lat: 50.1109, lon: 8.6821 }, // Frankfurt
        'ap-southeast-1': { lat: 1.3521, lon: 103.8198 }, // Singapore
        'ap-northeast-1': { lat: 35.6762, lon: 139.6503 }, // Tokyo
    };
    return regionMap[region.toLowerCase()] || "UNKNOWN";
}
/**
 * Collect geographic context
 */
export async function collectGeo(appState) {
    try {
        const [origin, gateway, dbRegion, pingMs] = await Promise.all([
            getOrigin(),
            getGatewayRegion(appState),
            getDbRegion(appState),
            pingGateway(appState),
        ]);
        // Build route label
        let routeLabel = "UNKNOWN";
        if (origin.label !== "UNKNOWN" && gateway.region !== "UNKNOWN") {
            routeLabel = `${origin.label} → ${gateway.region}`;
        }
        // Get gateway lat/lon if region is known
        let gatewayLatLon = undefined;
        if (gateway.region !== "UNKNOWN") {
            gatewayLatLon = regionToLatLon(gateway.region);
        }
        // Get DB lat/lon if region is known
        let dbLatLon = undefined;
        if (dbRegion !== "UNKNOWN") {
            dbLatLon = regionToLatLon(dbRegion);
        }
        // Determine confidence
        let confidence = "UNKNOWN";
        if (origin.source === "MANUAL" && gateway.region !== "UNKNOWN") {
            confidence = "HIGH";
        }
        else if (origin.label !== "UNKNOWN" || gateway.region !== "UNKNOWN") {
            confidence = "MEDIUM";
        }
        else if (origin.label === "UNKNOWN" && gateway.region === "UNKNOWN") {
            confidence = "UNKNOWN";
        }
        else {
            confidence = "LOW";
        }
        // Determine source
        const source = origin.source === "MANUAL" ? "MANUAL" :
            origin.source === "LOCAL_IP" ? "LOCAL_IP" :
                gateway.source === "AWS_META" ? "AWS_META" :
                    "NONE";
        const data = {
            originLabel: origin.label,
            originRegion: origin.region,
            originLatLon: origin.latLon,
            gatewayRegion: gateway.region,
            gatewayLatLon,
            dbRegion,
            dbLatLon,
            routeLabel,
            pingMs,
            pingClass: pingMs !== "UNKNOWN" ? getLatencyClass(pingMs) : "UNKNOWN",
            confidence,
            source,
        };
        // Phase 9: Determine status
        const now = Date.now();
        let status = 'LIVE';
        let reasonCode;
        let message;
        let action;
        if (!ALLOW_GEO_LOOKUP && source === "NONE") {
            status = 'DISABLED';
            reasonCode = 'GEO_LOOKUP_DISABLED';
            message = 'Geo lookup off';
            action = 'system enable-geo';
        }
        else if (confidence === "UNKNOWN" || (source === "NONE" && origin.label === "UNKNOWN" && gateway.region === "UNKNOWN")) {
            status = 'UNAVAILABLE';
            reasonCode = 'NO_GEO_DATA';
            message = 'No geo data available';
            action = 'system enable-geo';
        }
        else {
            status = 'LIVE';
        }
        return {
            status,
            asOf: now,
            data,
            source: 'collector_geo',
            staleAfterMs: 30000, // Geo data changes slowly
            reasonCode,
            message,
            action,
        };
    }
    catch (error) {
        return {
            status: 'UNAVAILABLE',
            asOf: Date.now(),
            source: 'collector_geo',
            staleAfterMs: 30000,
            reasonCode: 'COLLECTION_ERROR',
            message: error.message || 'Unknown error',
            action: 'system status',
        };
    }
}
//# sourceMappingURL=collector_geo.js.map