/**
 * Health Checker + SLO Monitor — 健康检查器与 SLO 监控
 *
 * HealthChecker: 对数据库连通性、磁盘空间、内存使用执行真实检查。
 * SLOMonitor: C-9 修复 — 补全 SLO 监控核心功能（错误率、延迟分布、吞吐量、燃烧速率）。
 *
 * @see docs/生产级通用 AI Agent 智能体桌面应用：完整设计与构建指南.html — 第十一章
 */

import { existsSync } from 'fs';
import { app } from 'electron';
import type Database from 'better-sqlite3';

export interface HealthReport {
  healthy: boolean;
  checks: HealthCheck[];
  timestamp: Date;
}

export interface HealthCheck {
  name: string;
  healthy: boolean;
  latencyMs?: number;
  error?: string;
}

export class HealthChecker {
  /**
   * @param getDB 数据库获取器（用于真实验证数据库连通性）
   * @param dbPath 数据库文件路径（后备：文件存在性检查）
   */
  constructor(
    private getDB?: () => Database.Database,
    private dbPath?: string,
  ) {}

  async check(): Promise<HealthReport> {
    const checks: HealthCheck[] = [];
    checks.push(await this.checkDatabase());
    checks.push(await this.checkFreeMemory());
    checks.push(await this.checkMemoryUsage());
    const allHealthy = checks.every((c) => c.healthy);
    return { healthy: allHealthy, checks, timestamp: new Date() };
  }

  private async checkDatabase(): Promise<HealthCheck> {
    const start = Date.now();
    try {
      // 优先使用注入的 DB 实例执行真实 ping
      if (this.getDB) {
        const db = this.getDB();
        // 执行真实查询验证数据库连通性
        db.prepare('SELECT 1').get();
        return { name: 'database', healthy: true, latencyMs: Date.now() - start };
      }
      // 后备：检查数据库文件是否存在
      if (this.dbPath && existsSync(this.dbPath)) {
        return { name: 'database', healthy: true, latencyMs: Date.now() - start };
      }
      return { name: 'database', healthy: false, error: 'Database not available' };
    } catch (error) {
      return {
        name: 'database',
        healthy: false,
        error: error instanceof Error ? error.message : String(error),
      };
    }
  }

  private async checkFreeMemory(): Promise<HealthCheck> {
    try {
      const userDataPath = app.getPath('userData');
      if (!existsSync(userDataPath)) {
        return { name: 'free_memory', healthy: false, error: 'User data path not accessible' };
      }
      // 检查实际可用内存（Windows/Linux 返回字节数）
      const { freemem } = await import('os');
      const freeBytes = freemem();
      const freeMB = freeBytes / (1024 * 1024);
      // 少于 200MB 视为不健康
      if (freeMB < 200) {
        return {
          name: 'free_memory',
          healthy: false,
          error: `Free memory critically low: ${freeMB.toFixed(0)}MB available`,
        };
      }
      return { name: 'free_memory', healthy: true };
    } catch (error) {
      return {
        name: 'free_memory',
        healthy: false,
        error: error instanceof Error ? error.message : String(error),
      };
    }
  }

  private async checkMemoryUsage(): Promise<HealthCheck> {
    const used = process.memoryUsage();
    const heapUsedMB = used.heapUsed / 1024 / 1024;
    const thresholdMB = 512;
    return {
      name: 'memory_usage',
      healthy: heapUsedMB < thresholdMB,
      ...(heapUsedMB >= thresholdMB
        ? { error: `Heap usage ${heapUsedMB.toFixed(0)}MB exceeds threshold ${thresholdMB}MB` }
        : {}),
    };
  }
}

// ===== C-9 修复: SLO Monitor — SLO 监控核心功能 =====

/**
 * SLO 监控配置
 */
export interface SLOConfig {
  /** SLO 目标（如 0.999 表示 99.9% 可用性） */
  target: number;
  /** 滑动窗口大小（毫秒，默认 5 分钟） */
  windowMs: number;
  /** 延迟分位数（如 0.95 表示 P95） */
  latencyPercentiles: number[];
  /** 延迟告警阈值（毫秒） */
  latencyThresholdMs: number;
}

/**
 * SLO 请求记录
 */
interface SLORequestRecord {
  timestamp: number;
  latencyMs: number;
  success: boolean;
}

/**
 * SLO 状态报告
 */
export interface SLOStatus {
  /** 当前错误率（0-1） */
  errorRate: number;
  /** 当前吞吐量（请求/秒） */
  throughput: number;
  /** 平均延迟（毫秒） */
  avgLatencyMs: number;
  /** 延迟分位数 */
  percentiles: Record<string, number>;
  /** 燃烧速率（实际错误率 / 错误预算） */
  burnRate: number;
  /** SLO 目标 */
  target: number;
  /** 错误预算（1 - target） */
  errorBudget: number;
  /** 是否违反 SLO */
  violated: boolean;
  /** 窗口内总请求数 */
  totalRequests: number;
  /** 窗口内错误请求数 */
  errorRequests: number;
  /** 时间戳 */
  timestamp: Date;
}

/**
 * SLO Monitor — SLO 监控器
 *
 * C-9 修复: 补全 SLO 监控核心功能
 *
 * 功能：
 * 1. 错误率追踪 — 记录请求成功/失败，计算滑动窗口内错误率
 * 2. 延迟分布追踪 — 记录请求延迟，计算 P50/P95/P99 分位数
 * 3. 吞吐量追踪 — 计算每秒请求数
 * 4. 燃烧速率计算 — 实际错误率 / 错误预算，>1 表示 SLO 即将违反
 *
 * @see docs/生产级通用 AI Agent 智能体桌面应用：完整设计与构建指南.html — 第十一章
 */
export class SLOMonitor {
  private records: SLORequestRecord[] = [];
  private readonly config: SLOConfig;

  constructor(config: Partial<SLOConfig> = {}) {
    this.config = {
      target: 0.999,
      windowMs: 5 * 60 * 1000, // 5 分钟
      latencyPercentiles: [0.5, 0.95, 0.99],
      latencyThresholdMs: 5000,
      ...config,
    };
  }

  /**
   * 记录一次请求
   * @param latencyMs 延迟（毫秒）
   * @param success 是否成功
   */
  recordRequest(latencyMs: number, success: boolean): void {
    const record: SLORequestRecord = {
      timestamp: Date.now(),
      latencyMs,
      success,
    };
    this.records.push(record);
    // 清理过期记录
    this.cleanup();
  }

  /**
   * 清理窗口外的过期记录
   */
  private cleanup(): void {
    const cutoff = Date.now() - this.config.windowMs;
    // 保留最近 10 分钟的数据（2 倍窗口），避免边界效应
    this.records = this.records.filter((r) => r.timestamp >= cutoff);
  }

  /**
   * 获取当前 SLO 状态
   */
  getStatus(): SLOStatus {
    this.cleanup();

    const now = Date.now();
    const windowStart = now - this.config.windowMs;
    const windowRecords = this.records.filter((r) => r.timestamp >= windowStart);

    const totalRequests = windowRecords.length;
    const errorRequests = windowRecords.filter((r) => !r.success).length;
    const errorRate = totalRequests > 0 ? errorRequests / totalRequests : 0;

    const throughput = totalRequests / (this.config.windowMs / 1000);

    const latencies = windowRecords.map((r) => r.latencyMs).sort((a, b) => a - b);
    const avgLatencyMs = latencies.length > 0
      ? latencies.reduce((sum, l) => sum + l, 0) / latencies.length
      : 0;

    const percentiles: Record<string, number> = {};
    for (const p of this.config.latencyPercentiles) {
      const key = `P${(p * 100).toFixed(0)}`;
      percentiles[key] = this.calculatePercentile(latencies, p);
    }

    const errorBudget = 1 - this.config.target;
    const burnRate = errorBudget > 0 ? errorRate / errorBudget : 0;

    return {
      errorRate,
      throughput,
      avgLatencyMs,
      percentiles,
      burnRate,
      target: this.config.target,
      errorBudget,
      violated: burnRate > 1,
      totalRequests,
      errorRequests,
      timestamp: new Date(),
    };
  }

  /**
   * 计算分位数
   */
  private calculatePercentile(sortedValues: number[], percentile: number): number {
    if (sortedValues.length === 0) return 0;
    const index = Math.ceil(percentile * sortedValues.length) - 1;
    return sortedValues[Math.max(0, index)];
  }

  /**
   * 重置所有记录
   */
  reset(): void {
    this.records = [];
  }

  /**
   * 获取配置
   */
  getConfig(): SLOConfig {
    return { ...this.config };
  }
}
