import type { Item, EvaluateDetail, EvaluateResult } from './types';
import { parseExpression } from './parser';

// ─── token 渲染 ─────────────────────────────────────────────

function renderTokens(tokens: Item[], displayMap: Record<string, string>): string {
  return tokens
    .map((t) => {
      if (t.type === 'number' && t.label) return t.label;
      if (t.type === 'operator') return displayMap[t.value] || t.value;
      if (t.type === 'logic') return displayMap[t.value] || t.value;
      if (t.type === 'operand') return displayMap[t.value] || t.label || t.value;
      return t.value;
    })
    .join(' ');
}

// ─── OR 分支拆分 ────────────────────────────────────────────

function splitOrBranches(tokens: Item[]): Item[][] {
  const branches: Item[][] = [];
  let current: Item[] = [];
  let depth = 0;

  for (const t of tokens) {
    if (t.type === 'leftParen') depth++;
    else if (t.type === 'rightParen') depth--;

    if (depth === 0 && t.type === 'logic' && t.value === '||') {
      branches.push(current);
      current = [];
    } else {
      current.push(t);
    }
  }
  if (current.length > 0) branches.push(current);
  return branches;
}

function branchContains(branch: Item[], vars: Set<string>): boolean {
  return branch.some((t) => t.type === 'operand' && vars.has(t.value));
}

// ─── 原子条件提取 ──────────────────────────────────────────

/**
 * 将 token 列表递归拆解为原子比较条件的 token 组。
 *
 * 步骤：
 *  1. 递归去掉最外层匹配的括号
 *  2. 在顶层 && / || 处拆分
 *  3. 对仍含括号的片段递归处理
 *
 * 例如 `(coVal>10 && coVal<=50) || co2Val<0.5` →
 *  [[coVal,>,10], [coVal,<=,50], [co2Val,<,0.5]]
 */
function extractAtomicSegments(tokens: Item[]): Item[][] {
  // 递归去掉最外层匹配的括号
  while (tokens.length >= 2 && tokens[0].type === 'leftParen') {
    let d = 0;
    let matched = true;
    for (let i = 0; i < tokens.length; i++) {
      if (tokens[i].type === 'leftParen') d++;
      if (tokens[i].type === 'rightParen') d--;
      if (d === 0 && i < tokens.length - 1) { matched = false; break; }
    }
    if (matched) tokens = tokens.slice(1, -1);
    else break;
  }

  // 在顶层 && / || 处拆分
  const segments: Item[][] = [];
  let current: Item[] = [];
  let depth = 0;

  for (const t of tokens) {
    if (t.type === 'leftParen') depth++;
    else if (t.type === 'rightParen') depth--;

    if (depth === 0 && t.type === 'logic') {
      if (current.length > 0) { segments.push(current); current = []; }
    } else {
      current.push(t);
    }
  }
  if (current.length > 0) segments.push(current);

  // 对仍含括号的片段递归
  return segments.flatMap((s) =>
    s.some((t) => t.type === 'leftParen') ? extractAtomicSegments(s) : [s],
  );
}

// ─── 对外接口 ───────────────────────────────────────────────

/**
 * 从表达式中提取涉及指定关键字的条件，返回可读解释。
 *
 * @param expr       - 表达式，如 "coValOut>=0 && coValOut<5"
 * @param reasons    - 关键字列表，如 ['coValOut', 'o2ValOut']
 * @param operandSet - 操作数集合
 * @param displayMap - 变量名/运算符 → 中文标签映射
 * @returns { passes, details, summary }
 */
export function evaluateExpression(
  expr: string,
  reasons: string[],
  operandSet: Set<string>,
  displayMap?: Record<string, string>,
): EvaluateResult {
  const tokens = parseExpression(expr, operandSet);
  if (tokens.length === 0) {
    return { passes: false, details: [], summary: '表达式为空或无法解析' };
  }

  const relevantVars = new Set(reasons);

  // 按顶层 || 拆分，只保留涉及传入关键字的 OR 分支
  const branches = splitOrBranches(tokens).filter((b) => branchContains(b, relevantVars));

  if (branches.length === 0) {
    return {
      passes: false,
      details: [],
      summary: `表达式中未找到涉及 ${reasons.join('、')} 的条件`,
    };
  }

  // 逐分支拆解为原子条件，只保留涉及 reasons 的
  const allDetails: EvaluateDetail[] = branches.flatMap((b) => {
    const atoms = extractAtomicSegments(b);
    return atoms
      .filter((atom) => atom.some((t) => t.type === 'operand' && relevantVars.has(t.value)))
      .map((atom) => ({
        condition: renderTokens(atom, displayMap || {}),
        passes: true,
      }));
  });

  if (allDetails.length === 0) {
    return {
      passes: false,
      details: [],
      summary: `表达式中未找到涉及 ${reasons.join('、')} 的条件`,
    };
  }

  const summary = allDetails.map((d) => d.condition).join('，');
  return { passes: true, details: allDetails, summary };
}

/**
 * evaluateExpression 的简化版，直接返回匹配条件的文本，用 ; 连接。
 *
 * @param expr       - 表达式
 * @param reasons    - 关键字列表
 * @param operandSet - 操作数集合
 * @param displayMap - 中文标签映射
 * @returns 匹配条件的可读文本，如 "闭外氧气 < 20;闭外一氧化碳 ≥ 0 且 闭外一氧化碳 < 5"
 */
export function evaluateExpressionLite(
  expr: string,
  reasons: string[],
  operandSet: Set<string>,
  displayMap?: Record<string, string>,
): string[] {
  const tokens = parseExpression(expr, operandSet);
  if (tokens.length === 0) return [];

  const relevantVars = new Set(reasons);
  const branches = splitOrBranches(tokens).filter((b) => branchContains(b, relevantVars));

  return branches
    .flatMap((b) => extractAtomicSegments(b))
    .filter((atom) => atom.some((t) => t.type === 'operand' && relevantVars.has(t.value)))
    .map((atom) => renderTokens(atom, displayMap || {}));
}
