/**
 * Graph Model - 图数据模型层
 * 
 * 职责：
 * - 管理节点和边的数据
 * - 维护图的逻辑结构（父子关系）
 * - 提供数据操作API
 * - 支持序列化/反序列化
 * 
 * 设计原则：
 * - 纯数据操作，不涉及渲染
 * - 可观察的数据变更
 * - 支持撤销/重做
 */

import type { 
  Node, NodeData, NodeStyle,
  Edge, EdgeData, EdgeStyle,
  Point, LayoutType, SerializedGraph, GraphData
} from './types'

/** 生成唯一ID */
function generateId(prefix: string = 'node'): string {
  return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
}

/**
 * 图数据模型
 */
export class GraphModel {
  private _nodes: Map<string, Node> = new Map()
  private _edges: Map<string, Edge> = new Map()
  private _rootId: string | null = null
  private _layoutType: LayoutType = 'radial-mindmap'
  
  // 父子关系索引
  private _childrenMap: Map<string, string[]> = new Map()
  private _parentMap: Map<string, string> = new Map()
  
  // 变更监听器
  private _changeListeners: Set<() => void> = new Set()

  /** 当前数据的 modified 时间戳（从服务器同步） */
  modified: string = ''

  constructor(data?: Partial<GraphData>) {
    if (data) {
      if (data.nodes) this.loadNodes(data.nodes)
      if (data.edges) this.loadEdges(data.edges)
      if (data.layoutType) this._layoutType = data.layoutType
    }
  }

  // ===== 节点操作 =====

  /** 获取所有节点 */
  get nodes(): Node[] {
    return Array.from(this._nodes.values())
  }

  /** 获取节点 */
  getNode(id: string): Node | undefined {
    return this._nodes.get(id)
  }

  /** 添加节点 */
  addNode(data: Partial<NodeData>, position?: Point): Node {
    const id = data.id || generateId('node')
    
    const node: Node = {
      id,
      label: data.label || '新节点',
      isRoot: data.isRoot || false,
      position: position || { x: 0, y: 0 },
      size: { width: 100, height: 36 },
      level: 0,
      children: [],
      collapsed: false,
      hidden: false,
      style: data.style,
      ...data
    }

    this._nodes.set(id, node)
    
    // 设置根节点
    if (data.isRoot) {
      this._rootId = id
    }

    this._childrenMap.set(id, [])
    this._notifyChange()
    
    return node
  }

  /** 更新节点 */
  updateNode(id: string, updates: Partial<Node>): Node | undefined {
    const node = this._nodes.get(id)
    if (!node) return undefined

    const updated = { ...node, ...updates }
    this._nodes.set(id, updated)
    this._notifyChange()
    
    return updated
  }

  /** 更新节点位置 */
  updateNodePosition(id: string, position: Point): void {
    const node = this._nodes.get(id)
    if (node) {
      node.position = position
      this._notifyChange()
    }
  }

  /** 删除节点（递归删除子节点） */
  removeNode(id: string): string[] {
    const removedIds: string[] = []
    
    const removeRecursive = (nodeId: string) => {
      const children = this._childrenMap.get(nodeId) || []
      children.forEach(childId => removeRecursive(childId))
      
      // 删除相关边
      this._edges.forEach((edge, edgeId) => {
        if (edge.source === nodeId || edge.target === nodeId) {
          this._edges.delete(edgeId)
        }
      })
      
      // 删除节点
      this._nodes.delete(nodeId)
      this._childrenMap.delete(nodeId)
      this._parentMap.delete(nodeId)
      removedIds.push(nodeId)
    }

    // 从父节点的children中移除
    const parentId = this._parentMap.get(id)
    if (parentId) {
      const siblings = this._childrenMap.get(parentId) || []
      const index = siblings.indexOf(id)
      if (index > -1) {
        siblings.splice(index, 1)
      }
    }

    removeRecursive(id)
    this._notifyChange()
    
    return removedIds
  }

  // ===== 边操作 =====

  /** 获取所有边 */
  get edges(): Edge[] {
    return Array.from(this._edges.values())
  }

  /** 获取边 */
  getEdge(id: string): Edge | undefined {
    return this._edges.get(id)
  }

  /** 添加边 */
  addEdge(source: string, target: string, data?: Partial<EdgeData>): Edge | undefined {
    if (!this._nodes.has(source) || !this._nodes.has(target)) {
      return undefined
    }

    const id = data?.id || `edge-${source}-${target}`
    
    const edge: Edge = {
      id,
      source,
      target,
      type: data?.type || 'bezier',
      style: data?.style || undefined,
      ...data
    }

    this._edges.set(id, edge)
    
    // 更新父子关系
    this._parentMap.set(target, source)
    const children = this._childrenMap.get(source) || []
    if (!children.includes(target)) {
      children.push(target)
    }
    
    // 更新层级
    this._updateLevels()
    
    this._notifyChange()
    return edge
  }

  /** 删除边 */
  removeEdge(id: string): void {
    const edge = this._edges.get(id)
    if (!edge) return

    // 更新父子关系
    this._parentMap.delete(edge.target)
    const children = this._childrenMap.get(edge.source) || []
    const index = children.indexOf(edge.target)
    if (index > -1) {
      children.splice(index, 1)
    }

    this._edges.delete(id)
    this._notifyChange()
  }

  // ===== 树结构操作 =====

  /** 获取根节点 */
  get root(): Node | undefined {
    return this._rootId ? this._nodes.get(this._rootId) : undefined
  }

  /** 获取子节点 */
  getChildren(nodeId: string): Node[] {
    const childrenIds = this._childrenMap.get(nodeId) || []
    return childrenIds
      .map(id => this._nodes.get(id))
      .filter((n): n is Node => n !== undefined)
  }

  /** 获取父节点 */
  getParent(nodeId: string): Node | undefined {
    const parentId = this._parentMap.get(nodeId)
    return parentId ? this._nodes.get(parentId) : undefined
  }

  /** 获取子孙节点（递归） */
  getDescendants(nodeId: string): Node[] {
    const result: Node[] = []
    const queue = [nodeId]
    
    while (queue.length > 0) {
      const currentId = queue.shift()!
      const children = this._childrenMap.get(currentId) || []
      
      for (const childId of children) {
        const child = this._nodes.get(childId)
        if (child) {
          result.push(child)
          queue.push(childId)
        }
      }
    }
    
    return result
  }

  /** 添加子节点 */
  addChild(parentId: string, data?: Partial<NodeData>): Node | undefined {
    const parent = this._nodes.get(parentId)
    if (!parent) return undefined

    const child = this.addNode(data || { label: '新节点' })
    
    // 更新父子关系
    this._parentMap.set(child.id, parentId)
    const children = this._childrenMap.get(parentId) || []
    children.push(child.id)
    
    // 更新层级
    this._updateLevels()
    
    // 创建边
    this.addEdge(parentId, child.id)
    
    return child
  }

  /**
   * 在当前节点和其父节点之间插入一个新父节点
   * @param nodeId 当前节点ID
   * @param data 新父节点的数据
   * @returns 新创建的父节点
   */
  insertParent(nodeId: string, data?: Partial<NodeData>): Node | undefined {
    const node = this._nodes.get(nodeId)
    if (!node || node.isRoot) return undefined // 根节点不能添加父节点

    const oldParentId = this._parentMap.get(nodeId)
    if (!oldParentId) return undefined

    const oldParent = this._nodes.get(oldParentId)
    if (!oldParent) return undefined

    // 创建新节点
    const newParent = this.addNode(data || { label: '新节点' })

    // 1. 从旧父节点的 children 中移除当前节点
    const oldParentChildren = this._childrenMap.get(oldParentId) || []
    const idx = oldParentChildren.indexOf(nodeId)
    if (idx > -1) {
      oldParentChildren.splice(idx, 1)
    }

    // 2. 删除旧边
    const oldEdgeId = `edge-${oldParentId}-${nodeId}`
    this._edges.delete(oldEdgeId)

    // 3. 设置新节点的父节点为旧父节点
    this._parentMap.set(newParent.id, oldParentId)
    oldParentChildren.push(newParent.id)

    // 4. 设置当前节点的父节点为新节点
    this._parentMap.set(nodeId, newParent.id)
    const newParentChildren = this._childrenMap.get(newParent.id) || []
    newParentChildren.push(nodeId)
    this._childrenMap.set(newParent.id, newParentChildren)

    // 5. 创建新边
    this.addEdge(oldParentId, newParent.id)
    this.addEdge(newParent.id, nodeId)

    // 更新层级
    this._updateLevels()

    return newParent
  }

  /** 折叠/展开节点 */
  toggleCollapse(nodeId: string): void {
    const node = this._nodes.get(nodeId)
    if (!node) return

    node.collapsed = !node.collapsed
    
    // 隐藏/显示子孙节点
    const descendants = this.getDescendants(nodeId)
    descendants.forEach(d => {
      d.hidden = node.collapsed
    })
    
    this._notifyChange()
  }

  /** 恢复折叠状态（加载数据后调用） */
  restoreCollapseState(): void {
    // 遍历所有折叠的节点，隐藏其子孙节点
    this._nodes.forEach(node => {
      if (node.collapsed) {
        const descendants = this.getDescendants(node.id)
        descendants.forEach(d => {
          d.hidden = true
        })
      }
    })
  }

  // ===== 布局类型 =====

  get layoutType(): LayoutType {
    return this._layoutType
  }

  setLayoutType(type: LayoutType): void {
    this._layoutType = type
    this._notifyChange()
  }

  // ===== 序列化 =====

  /** 序列化为JSON（最小化输出，空字段不保存） */
  serialize(): SerializedGraph {
    return {
      nodes: this.nodes.map(n => {
        const nodeData: Record<string, unknown> = {
          id: n.id,
          label: n.label
        }
        // 只保存非空字段
        if (n.isRoot) nodeData.isRoot = true
        if (n.description) nodeData.description = n.description
        if (n.position) nodeData.position = n.position
        if (n.style) nodeData.style = n.style
        if (n.collapsed) nodeData.collapsed = true
        return nodeData as any
      }),
      edges: this.edges.map(e => {
        const edgeData: Record<string, unknown> = {
          id: e.id,
          source: e.source,
          target: e.target
        }
        if (e.type && e.type !== 'bezier') edgeData.type = e.type
        if (e.style) edgeData.style = e.style
        return edgeData as any
      }),
      layoutType: this._layoutType
    }
  }

  /** 从JSON加载 */
  static deserialize(data: SerializedGraph): GraphModel {
    const model = new GraphModel()
    model.loadNodes(data.nodes.map(n => ({
      ...n,
      // 保留保存的位置，如果没有则使用默认值
      position: n.position || { x: 0, y: 0 },
      size: n.size || { width: 100, height: 36 },
      level: n.level || 0,
      children: [],
      hidden: n.hidden || false
    })))
    model.loadEdges(data.edges)
    model._layoutType = data.layoutType
    return model
  }

  // ===== 私有方法 =====

  private loadNodes(nodes: Node[]): void {
    nodes.forEach(n => {
      this._nodes.set(n.id, n)
      this._childrenMap.set(n.id, [])
      if (n.isRoot) this._rootId = n.id
    })
  }

  private loadEdges(edges: EdgeData[]): void {
    edges.forEach(e => {
      this.addEdge(e.source, e.target, e)
    })
  }

  private _updateLevels(): void {
    if (!this._rootId) return
    
    const updateLevel = (nodeId: string, level: number) => {
      const node = this._nodes.get(nodeId)
      if (node) {
        node.level = level
        const children = this._childrenMap.get(nodeId) || []
        children.forEach(childId => updateLevel(childId, level + 1))
      }
    }
    
    updateLevel(this._rootId, 0)
  }

  private _notifyChange(): void {
    this._changeListeners.forEach(listener => listener())
  }

  // ===== 变更监听 =====

  onChange(listener: () => void): () => void {
    this._changeListeners.add(listener)
    return () => this._changeListeners.delete(listener)
  }

  // ===== 工具方法 =====

  /** 创建默认图（带根节点） */
  static createDefault(label: string = '中心主题'): GraphModel {
    const model = new GraphModel()
    model.addNode({
      id: 'root',
      label,
      isRoot: true
    })
    model._rootId = 'root'
    return model
  }

  /** 克隆图 */
  clone(): GraphModel {
    return GraphModel.deserialize(this.serialize())
  }

  /** 获取节点总数 */
  get nodeCount(): number {
    return this._nodes.size
  }

  /** 获取边总数 */
  get edgeCount(): number {
    return this._edges.size
  }
}

// 导出类型

/** 图模型接口 */
export interface IGraphModel {
  nodes: Node[]
  edges: Edge[]
  root: Node | undefined
  layoutType: LayoutType
  getNode(id: string): Node | undefined
  getChildren(nodeId: string): Node[]
  getParent(nodeId: string): Node | undefined
  getDescendants(nodeId: string): Node[]
  updateNodePosition(id: string, position: Point): void
  serialize(): SerializedGraph
}
