/**
 * 表达式解析和生成工具
 * 处理 ${...} 格式的表达式
 */

/**
 * 表达式命名空间
 */
export enum ExpressionNamespace {
  /** 节点数据 */
  NODES = 'nodes',
  /** 工作流数据 */
  WORKFLOW = 'workflow',
  /** 环境变量 */
  ENV = 'env',
}

/**
 * 表达式信息
 */
export interface ExpressionInfo {
  /** 原始表达式 */
  raw: string
  /** 是否为表达式 */
  isExpression: boolean
  /** 命名空间 */
  namespace?: ExpressionNamespace
  /** 路径部分 */
  path?: string
  /** 解析后的段 */
  segments?: string[]
}

/**
 * 检查是否为表达式
 */
export function isExpression(value: any): boolean {
  return typeof value === 'string' && /^\$\{.+\}$/.test(value.trim())
}

/**
 * 解析表达式
 * @param expression 表达式字符串
 * @returns 表达式信息
 */
export function parseExpression(expression: string): ExpressionInfo {
  const trimmed = expression.trim()

  if (!isExpression(trimmed)) {
    return {
      raw: expression,
      isExpression: false,
    }
  }

  // 提取 ${...} 中的内容
  const content = trimmed.slice(2, -1).trim()
  const segments = content.split('.')

  if (segments.length === 0) {
    return {
      raw: expression,
      isExpression: true,
    }
  }

  const namespace = segments[0] as ExpressionNamespace
  const path = segments.slice(1).join('.')

  return {
    raw: expression,
    isExpression: true,
    namespace,
    path,
    segments,
  }
}

/**
 * 生成节点输出字段表达式
 * @param nodeId 节点 ID
 * @param fieldPath 字段路径（如 output.body.email）
 */
export function generateNodeFieldExpression(nodeId: string, fieldPath: string): string {
  return `\${nodes.${nodeId}.${fieldPath}}`
}

/**
 * 解析节点字段表达式
 * @param expression 表达式（如 ${nodes.n1.output.body.email}）
 * @returns 节点ID和字段路径，如果不是节点表达式则返回null
 */
export function parseFieldExpression(expression: string): { nodeId: string; fieldPath: string } | null {
  const info = parseExpression(expression)
  if (info.namespace !== ExpressionNamespace.NODES || !info.segments || info.segments.length < 3) {
    return null
  }

  const nodeId = info.segments[1]
  if (!nodeId) {
    return null
  }

  const fieldPath = info.segments.slice(2).join('.')

  return { nodeId, fieldPath }
}

/**
 * 生成工作流输入字段表达式
 * @param fieldPath 字段路径（如 input.approver）
 */
export function generateWorkflowFieldExpression(fieldPath: string): string {
  return `\${workflow.${fieldPath}}`
}

/**
 * 生成环境变量表达式
 * @param varName 变量名
 */
export function generateEnvExpression(varName: string): string {
  return `\${env.${varName}}`
}

/**
 * 验证表达式语法
 * @param expression 表达式
 * @returns 是否有效
 */
export function validateExpression(expression: string): boolean {
  if (!isExpression(expression)) {
    return false
  }

  const info = parseExpression(expression)
  if (!info.namespace || !info.segments || info.segments.length < 2) {
    return false
  }

  // 验证命名空间
  const validNamespaces = Object.values(ExpressionNamespace)
  if (!validNamespaces.includes(info.namespace)) {
    return false
  }

  // 节点命名空间需要至少 3 段：nodes.nodeId.field
  if (info.namespace === ExpressionNamespace.NODES && info.segments.length < 3) {
    return false
  }

  return true
}

/**
 * 提取表达式中的节点依赖
 * @param expression 表达式
 * @returns 节点 ID 列表
 */
export function extractNodeDependencies(expression: string): string[] {
  const info = parseExpression(expression)
  if (info.namespace === ExpressionNamespace.NODES && info.segments && info.segments.length >= 2) {
    const nodeId = info.segments[1]
    if (nodeId) {
      return [nodeId]
    }
  }
  return []
}

/**
 * 提取配置对象中所有的节点依赖
 * @param config 配置对象
 * @returns 节点 ID 集合
 */
export function extractAllNodeDependencies(config: Record<string, any>): Set<string> {
  const dependencies = new Set<string>()

  function traverse(obj: any) {
    if (typeof obj === 'string') {
      const deps = extractNodeDependencies(obj)
      deps.forEach((dep) => dependencies.add(dep))
    } else if (Array.isArray(obj)) {
      obj.forEach(traverse)
    } else if (obj && typeof obj === 'object') {
      Object.values(obj).forEach(traverse)
    }
  }

  traverse(config)
  return dependencies
}

/**
 * 替换表达式中的节点 ID（用于节点重命名）
 * @param expression 原表达式
 * @param oldNodeId 旧节点 ID
 * @param newNodeId 新节点 ID
 */
export function replaceNodeIdInExpression(
  expression: string,
  oldNodeId: string,
  newNodeId: string,
): string {
  if (!isExpression(expression)) {
    return expression
  }

  const info = parseExpression(expression)
  if (
    info.namespace === ExpressionNamespace.NODES &&
    info.segments &&
    info.segments[1] === oldNodeId
  ) {
    const newSegments = [info.segments[0], newNodeId, ...info.segments.slice(2)]
    return `\${${newSegments.join('.')}}`
  }

  return expression
}

/**
 * 高亮表达式（用于显示）
 * @param expression 表达式
 * @returns HTML 字符串
 */
export function highlightExpression(expression: string): string {
  if (!isExpression(expression)) {
    return expression
  }

  const info = parseExpression(expression)
  if (!info.segments || info.segments.length === 0) {
    return expression
  }

  const parts = info.segments.map((seg, index) => {
    if (index === 0) {
      // 命名空间
      return `<span style="color: #0066cc; font-weight: bold;">${seg || ''}</span>`
    } else if (info.namespace === ExpressionNamespace.NODES && index === 1) {
      // 节点 ID
      return `<span style="color: #00aa00; font-weight: bold;">${seg || ''}</span>`
    } else {
      // 字段路径
      return `<span style="color: #666;">${seg || ''}</span>`
    }
  })

  return `<span style="font-family: monospace;">$\{${parts.join('.')}\}</span>`
}

