/**
 * 图数据结构
 * 用于 PageRank 算法
 */

import type { GraphEdge } from '../types.js';

export class Graph {
  /** 邻接表：from -> edges[] */
  private outEdges: Map<string, GraphEdge[]> = new Map();
  /** 反向邻接表：to -> edges[] */
  private inEdges: Map<string, GraphEdge[]> = new Map();
  /** 所有节点 */
  private nodes: Set<string> = new Set();

  /**
   * 添加边
   */
  addEdge(edge: GraphEdge): void {
    this.nodes.add(edge.from);
    this.nodes.add(edge.to);

    // 出边
    if (!this.outEdges.has(edge.from)) {
      this.outEdges.set(edge.from, []);
    }
    this.outEdges.get(edge.from)!.push(edge);

    // 入边
    if (!this.inEdges.has(edge.to)) {
      this.inEdges.set(edge.to, []);
    }
    this.inEdges.get(edge.to)!.push(edge);
  }

  /**
   * 获取所有节点
   */
  getNodes(): string[] {
    return Array.from(this.nodes);
  }

  /**
   * 获取节点的出边
   */
  getOutEdges(node: string): GraphEdge[] {
    return this.outEdges.get(node) || [];
  }

  /**
   * 获取节点的入边
   */
  getInEdges(node: string): GraphEdge[] {
    return this.inEdges.get(node) || [];
  }

  /**
   * 获取节点的出度（考虑权重）
   */
  getOutDegree(node: string): number {
    const edges = this.outEdges.get(node) || [];
    return edges.reduce((sum, e) => sum + e.weight, 0);
  }

  /**
   * 获取节点的入度（考虑权重）
   */
  getInDegree(node: string): number {
    const edges = this.inEdges.get(node) || [];
    return edges.reduce((sum, e) => sum + e.weight, 0);
  }

  /**
   * 获取边数量
   */
  getEdgeCount(): number {
    let count = 0;
    for (const edges of this.outEdges.values()) {
      count += edges.length;
    }
    return count;
  }

  /**
   * 清空图
   */
  clear(): void {
    this.outEdges.clear();
    this.inEdges.clear();
    this.nodes.clear();
  }

  /**
   * 是否为空
   */
  isEmpty(): boolean {
    return this.nodes.size === 0;
  }
}
