import type {
    HealthResponse,
    MetricResponse,
    ThreadDumpResponse,
    JvmMemoryInfo,
    CpuUsageInfo,
    ThreadInfo,
    HikariInfo,
    GcInfo,
    ThreadStateCount,
    SystemMetrics,
} from './types';

// API 基础路径
const ACTUATOR_BASE_URL = '/actuator';

/**
 * 原生 fetch 调用（actuator 接口不使用项目的 request 封装）
 */
const fetchActuator = async <T>(url: string): Promise<T> => {
    const response = await fetch(url);
    if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
};

/**
 * 获取健康检查信息
 */
export const getHealth = () =>
    fetchActuator<HealthResponse>(`${ACTUATOR_BASE_URL}/health`);

/**
 * 获取指标数据（通用）
 */
export const getMetric = (metricName: string, tag?: string) => {
    const url = tag
        ? `${ACTUATOR_BASE_URL}/metrics/${metricName}?tag=${encodeURIComponent(tag)}`
        : `${ACTUATOR_BASE_URL}/metrics/${metricName}`;
    return fetchActuator<MetricResponse>(url);
};

/**
 * 获取 JVM 内存信息（增强版：包含 committed 和区域详情）
 */
export const getJvmMemory = async (): Promise<JvmMemoryInfo> => {
    // 基础堆和非堆内存指标
    const [
        heapUsedRes, 
        heapMaxRes, 
        heapCommittedRes,
        nonHeapUsedRes, 
        nonHeapMaxRes,
        nonHeapCommittedRes
    ] = await Promise.all([
        getMetric('jvm.memory.used', 'area:heap'),
        getMetric('jvm.memory.max', 'area:heap'),
        getMetric('jvm.memory.committed', 'area:heap'),
        getMetric('jvm.memory.used', 'area:nonheap'),
        getMetric('jvm.memory.max', 'area:nonheap'),
        getMetric('jvm.memory.committed', 'area:nonheap'),
    ]);

    const heapUsed = heapUsedRes.measurements[0].value;
    const heapMax = heapMaxRes.measurements[0].value;
    const heapCommitted = heapCommittedRes.measurements[0].value;
    const nonHeapUsed = nonHeapUsedRes.measurements[0].value;
    const nonHeapMax = nonHeapMaxRes.measurements[0].value;
    const nonHeapCommitted = nonHeapCommittedRes.measurements[0].value;

    // 尝试获取详细区域信息（可能因GC类型不同而失败）
    let regions;
    try {
        const [edenUsed, edenMax, edenCommitted, oldUsed, oldMax, oldCommitted, 
               survivorUsed, survivorMax, survivorCommitted, metaspaceUsed, metaspaceMax, metaspaceCommitted] = 
            await Promise.all([
                // Eden 区
                getMetric('jvm.memory.used', 'id:G1 Eden Space').catch(() => null),
                getMetric('jvm.memory.max', 'id:G1 Eden Space').catch(() => null),
                getMetric('jvm.memory.committed', 'id:G1 Eden Space').catch(() => null),
                // Old Gen
                getMetric('jvm.memory.used', 'id:G1 Old Gen').catch(() => null),
                getMetric('jvm.memory.max', 'id:G1 Old Gen').catch(() => null),
                getMetric('jvm.memory.committed', 'id:G1 Old Gen').catch(() => null),
                // Survivor
                getMetric('jvm.memory.used', 'id:G1 Survivor Space').catch(() => null),
                getMetric('jvm.memory.max', 'id:G1 Survivor Space').catch(() => null),
                getMetric('jvm.memory.committed', 'id:G1 Survivor Space').catch(() => null),
                // Metaspace
                getMetric('jvm.memory.used', 'id:Metaspace').catch(() => null),
                getMetric('jvm.memory.max', 'id:Metaspace').catch(() => null),
                getMetric('jvm.memory.committed', 'id:Metaspace').catch(() => null),
            ]);

        regions = {
            eden: edenUsed && edenMax && edenCommitted ? {
                used: edenUsed.measurements[0].value,
                max: edenMax.measurements[0].value,
                committed: edenCommitted.measurements[0].value,
            } : undefined,
            oldGen: oldUsed && oldMax && oldCommitted ? {
                used: oldUsed.measurements[0].value,
                max: oldMax.measurements[0].value,
                committed: oldCommitted.measurements[0].value,
            } : undefined,
            survivor: survivorUsed && survivorMax && survivorCommitted ? {
                used: survivorUsed.measurements[0].value,
                max: survivorMax.measurements[0].value,
                committed: survivorCommitted.measurements[0].value,
            } : undefined,
            metaspace: metaspaceUsed && metaspaceMax && metaspaceCommitted ? {
                used: metaspaceUsed.measurements[0].value,
                max: metaspaceMax.measurements[0].value,
                committed: metaspaceCommitted.measurements[0].value,
            } : undefined,
        };
    } catch (error) {
        // 如果区域详情获取失败（可能是非G1 GC），忽略错误
        console.debug('无法获取内存区域详情，可能使用了非G1 GC收集器');
        regions = undefined;
    }

    return {
        heapUsed,
        heapMax,
        heapCommitted,
        heapPercent: (heapUsed / heapMax) * 100,
        nonHeapUsed,
        nonHeapMax,
        nonHeapCommitted,
        nonHeapPercent: (nonHeapUsed / nonHeapMax) * 100,
        regions,
    };
};

/**
 * 获取 CPU 使用率
 */
export const getCpuUsage = async (): Promise<CpuUsageInfo> => {
    const [systemCpuRes, processCpuRes] = await Promise.all([
        getMetric('system.cpu.usage'),
        getMetric('process.cpu.usage'),
    ]);

    return {
        systemCpu: systemCpuRes.measurements[0].value,
        processCpu: processCpuRes.measurements[0].value,
    };
};

/**
 * 获取线程信息
 */
export const getThreadInfo = async (): Promise<ThreadInfo> => {
    const [liveRes, daemonRes, peakRes] = await Promise.all([
        getMetric('jvm.threads.live'),
        getMetric('jvm.threads.daemon'),
        getMetric('jvm.threads.peak'),
    ]);

    return {
        live: liveRes.measurements[0].value,
        daemon: daemonRes.measurements[0].value,
        peak: peakRes.measurements[0].value,
    };
};

/**
 * 获取 HikariCP 连接池信息
 */
export const getHikariInfo = async (): Promise<HikariInfo> => {
    try {
        // 注意：根据 Spring Boot 版本不同，metric 名称可能是 hikaricp 或 hikari
        // 这里尝试 hikaricp，如果失败会降级处理
        const [activeRes, idleRes, maxRes, minRes, pendingRes] = await Promise.all([
            getMetric('hikaricp.connections.active'),
            getMetric('hikaricp.connections.idle'),
            getMetric('hikaricp.connections.max'),
            getMetric('hikaricp.connections.min'),
            getMetric('hikaricp.connections.pending'),
        ]);

        const active = activeRes.measurements[0].value;
        const idle = idleRes.measurements[0].value;
        const max = maxRes.measurements[0].value;
        const min = minRes.measurements[0].value;
        const pending = pendingRes.measurements[0].value;
        const total = active + idle;

        return {
            active,
            idle,
            max,
            min,
            pending,
            total,
            usagePercent: (total / max) * 100,
        };
    } catch (error) {
        // 如果 HikariCP 指标不可用，返回默认值
        return {
            active: 0,
            idle: 0,
            max: 0,
            min: 0,
            pending: 0,
            total: 0,
            usagePercent: 0,
        };
    }
};

/**
 * 获取 GC 统计信息
 */
export const getGcInfo = async (): Promise<GcInfo> => {
    try {
        // 先获取不带 tag 的 GC 指标，获取所有 GC 暂停时间的汇总数据
        const gcRes = await getMetric('jvm.gc.pause');

        const countMeasurement = gcRes.measurements.find(m => m.statistic === 'COUNT');
        const totalTimeMeasurement = gcRes.measurements.find(m => m.statistic === 'TOTAL_TIME');
        const maxMeasurement = gcRes.measurements.find(m => m.statistic === 'MAX');

        const count = countMeasurement?.value || 0;
        const totalTime = totalTimeMeasurement?.value || 0;
        const maxTime = maxMeasurement?.value || 0;
        const avgTime = count > 0 ? (totalTime / count) * 1000 : 0; // 转换为毫秒

        return {
            count,
            totalTime,
            maxTime,
            avgTime,
        };
    } catch (error) {
        console.warn('GC 指标获取失败，使用默认值:', error);
        // 如果 GC 指标不可用，返回默认值
        return {
            count: 0,
            totalTime: 0,
            maxTime: 0,
            avgTime: 0,
        };
    }
};

/**
 * 获取线程转储
 */
export const getThreadDump = () =>
    fetchActuator<ThreadDumpResponse>(`${ACTUATOR_BASE_URL}/threaddump`);

/**
 * 获取线程状态统计
 */
export const getThreadStateCount = async (): Promise<ThreadStateCount> => {
    const threadDump = await getThreadDump();

    const stateCount: ThreadStateCount = {
        RUNNABLE: 0,
        WAITING: 0,
        TIMED_WAITING: 0,
        BLOCKED: 0,
        NEW: 0,
        TERMINATED: 0,
    };

    threadDump.threads.forEach(thread => {
        if (stateCount.hasOwnProperty(thread.threadState)) {
            stateCount[thread.threadState]++;
        }
    });

    return stateCount;
};

/**
 * 获取所有系统指标（一次性获取）
 * 使用 Promise.allSettled 确保部分接口失败不会影响整体数据获取
 */
export const getAllMetrics = async (): Promise<SystemMetrics> => {
    const results = await Promise.allSettled([
        getHealth(),
        getJvmMemory(),
        getCpuUsage(),
        getThreadInfo(),
        getHikariInfo(),
        getGcInfo(),
        getThreadStateCount(),
    ]);

    // 提取成功的结果，失败的使用默认值
    const [healthResult, memoryResult, cpuResult, threadsResult, hikariResult, gcResult, threadStatesResult] = results;

    return {
        health: healthResult.status === 'fulfilled' ? healthResult.value : { status: 'UNKNOWN' },
        memory: memoryResult.status === 'fulfilled' ? memoryResult.value : {
            heapUsed: 0,
            heapMax: 0,
            heapCommitted: 0,
            heapPercent: 0,
            nonHeapUsed: 0,
            nonHeapMax: 0,
            nonHeapCommitted: 0,
            nonHeapPercent: 0,
        },
        cpu: cpuResult.status === 'fulfilled' ? cpuResult.value : { systemCpu: 0, processCpu: 0 },
        threads: threadsResult.status === 'fulfilled' ? threadsResult.value : { live: 0, daemon: 0, peak: 0 },
        hikari: hikariResult.status === 'fulfilled' ? hikariResult.value : {
            active: 0,
            idle: 0,
            max: 0,
            min: 0,
            pending: 0,
            total: 0,
            usagePercent: 0,
        },
        gc: gcResult.status === 'fulfilled' ? gcResult.value : {
            count: 0,
            totalTime: 0,
            maxTime: 0,
            avgTime: 0,
        },
        threadStates: threadStatesResult.status === 'fulfilled' ? threadStatesResult.value : {
            RUNNABLE: 0,
            WAITING: 0,
            TIMED_WAITING: 0,
            BLOCKED: 0,
            NEW: 0,
            TERMINATED: 0,
        },
        timestamp: Date.now(),
    };
};

/**
 * 动态调整日志级别
 */
export const updateLogLevel = async (loggerName: string, level: 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR') => {
    const response = await fetch(`${ACTUATOR_BASE_URL}/loggers/${loggerName}`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            configuredLevel: level,
        }),
    });
    if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
    }
};

/**
 * 获取日志配置
 */
export const getLoggers = () =>
    fetchActuator(`${ACTUATOR_BASE_URL}/loggers`);

/**
 * 获取环境变量
 */
export const getEnv = () =>
    fetchActuator(`${ACTUATOR_BASE_URL}/env`);
