//instance-health.js

const HEALTH_CHECK_INTERVAL = 5 * 60 * 1000;
const HEALTH_CHECK_TIMEOUT = 8000;
const MAX_CONSECUTIVE_FAILURES = 3;
const INITIAL_DELAY = 10000;
const IS_DEV = typeof window !== 'undefined' && window.location?.hostname === 'localhost';

class InstanceHealthChecker {
    constructor() {
        this.healthCache = new Map();
        this.checkTimers = {};
        this.listeners = [];
    }

    onHealthUpdate(callback) {
        this.listeners.push(callback);
    }

    notifyListeners(instances) {
        this.listeners.forEach((cb) => cb(instances));
    }

    async checkInstance(url, type = 'api') {
        const testPath = '/';
        const fullUrl = url.endsWith('/') ? `${url}${testPath.substring(1)}` : `${url}${testPath}`;

        const startTime = Date.now();
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), HEALTH_CHECK_TIMEOUT);

        try {
            const response = await fetch(fullUrl, {
                method: 'GET',
                signal: controller.signal,
            });

            clearTimeout(timeoutId);
            const latency = Date.now() - startTime;

            const existing = this.healthCache.get(url) || { url, failures: 0 };
            const status = response.ok || response.status === 401 || response.status === 404 ? 'online' : 'degraded';

            this.healthCache.set(url, {
                ...existing,
                status,
                latency,
                lastCheck: Date.now(),
                failures: response.ok ? 0 : existing.failures,
                type,
            });

            return { url, status, latency, online: response.ok };
        } catch (error) {
            clearTimeout(timeoutId);
            const existing = this.healthCache.get(url) || { url, failures: 0 };
            const newFailures = existing.failures + 1;
            const status = newFailures >= MAX_CONSECUTIVE_FAILURES ? 'offline' : 'degraded';

            this.healthCache.set(url, {
                url,
                status,
                latency: null,
                lastCheck: Date.now(),
                failures: newFailures,
                error: error.message,
                type,
            });

            return { url, status, latency: null, online: false, error: error.message };
        }
    }

    async checkAll(instances, type = 'api') {
        const checks = instances.map((inst) => {
            const url = typeof inst === 'string' ? inst : inst.url;
            return this.checkInstance(url, type);
        });

        const results = await Promise.allSettled(checks);
        return results.map((r) => r.value || { url: 'unknown', status: 'offline', online: false });
    }

    getHealthStatus(url) {
        return this.healthCache.get(url) || { url, status: 'unknown', latency: null, lastCheck: null };
    }

    getHealthyInstances(instances, type = 'api') {
        return instances.filter((inst) => {
            const url = typeof inst === 'string' ? inst : inst.url;
            const health = this.healthCache.get(url);
            return !health || health.status === 'online' || health.status === 'degraded';
        });
    }

    getHealthyAndSorted(instances, type = 'api') {
        const withHealth = instances.map((inst) => {
            const url = typeof inst === 'string' ? inst : inst.url;
            const health = this.healthCache.get(url);
            return {
                ...inst,
                healthStatus: health?.status || 'unknown',
                latency: health?.latency ?? null,
            };
        });

        return withHealth.sort((a, b) => {
            if (a.healthStatus === 'offline' && b.healthStatus !== 'offline') return 1;
            if (b.healthStatus === 'offline' && a.healthStatus !== 'offline') return -1;
            if (a.latency !== null && b.latency !== null) return a.latency - b.latency;
            if (a.latency !== null) return -1;
            if (b.latency !== null) return 1;
            return 0;
        });
    }

    startPeriodicCheck(instancesGetter, type = 'api') {
        if (this.checkTimers[type]) {
            clearInterval(this.checkTimers[type]);
        }

        if (IS_DEV) {
            console.log(`Health check disabled in dev mode for ${type}`);
            return;
        }

        const check = async () => {
            const instances = await instancesGetter(type);
            if (!instances || instances.length === 0) return;
            const results = await this.checkAll(instances, type);
            this.notifyListeners(results);
        };

        setTimeout(check, INITIAL_DELAY);
        this.checkTimers[type] = setInterval(check, HEALTH_CHECK_INTERVAL);
    }

    stopPeriodicCheck(type = 'api') {
        if (this.checkTimers[type]) {
            clearInterval(this.checkTimers[type]);
            delete this.checkTimers[type];
        }
    }

    stopAllChecks() {
        Object.keys(this.checkTimers).forEach((type) => this.stopPeriodicCheck(type));
    }

    async quickCheck(url, type = 'api') {
        return this.checkInstance(url, type);
    }

    getCachedStatus(url) {
        return this.healthCache.get(url);
    }

    clearCache() {
        this.healthCache.clear();
    }
}

export const instanceHealth = new InstanceHealthChecker();
