/**
 * @license
 * Copyright 2025 ReverseCraft
 * SPDX-License-Identifier: Apache-2.0
 */
export function buildCallGraph(e){const t=new Map,n=new Map,o=new Map;for(const r of e){for(const e of r.functions)o.has(e.name)||o.set(e.name,e);for(const e of r.calls)t.has(e.caller)||t.set(e.caller,new Set),t.get(e.caller).add(e.callee),n.has(e.callee)||n.set(e.callee,new Set),n.get(e.callee).add(e.caller)}return{calls:t,calledBy:n,functions:o}}export function getUpstreamTrace(e,t,n){const o={},r=new Set;function s(t,n){if(n<=0||r.has(t))return{};r.add(t);const o=e.calledBy.get(t);if(!o||0===o.size)return r.delete(t),{};const c={};for(const e of o)if(r.has(e))c[e]="Leaf";else{const t=s(e,n-1);c[e]=Object.keys(t).length>0?t:"Leaf"}return r.delete(t),c}const c=e.calledBy.get(t);if(c)for(const e of c){const t=s(e,n-1);o[e]=Object.keys(t).length>0?t:"Leaf"}return o}export function getDownstreamTrace(e,t,n){const o={},r=new Set;function s(t,n){if(n<=0||r.has(t))return{};r.add(t);const o=e.calls.get(t);if(!o||0===o.size)return r.delete(t),{};const c={};for(const e of o)if(r.has(e))c[e]="Leaf";else{const t=s(e,n-1);c[e]=Object.keys(t).length>0?t:"Leaf"}return r.delete(t),c}const c=e.calls.get(t);if(c)for(const e of c){const t=s(e,n-1);o[e]=Object.keys(t).length>0?t:"Leaf"}return o}function e(e,t){const n=Math.max(e.length,t.length);if(0===n)return 1;return 1-function(e,t){const n=[];for(let t=0;t<=e.length;t++)n[t]=[t];for(let e=0;e<=t.length;e++)n[0][e]=e;for(let o=1;o<=e.length;o++)for(let r=1;r<=t.length;r++){const s=e[o-1]===t[r-1]?0:1;n[o][r]=Math.min(n[o-1][r]+1,n[o][r-1]+1,n[o-1][r-1]+s)}return n[e.length][t.length]}(e.toLowerCase(),t.toLowerCase())/n}export function findSimilarFunctions(t,n,o=5){const r=[];for(const o of t.functions.keys()){if(o===n)continue;const t=e(n,o),s=o.toLowerCase().includes(n.toLowerCase())?.3:0;r.push({name:o,score:t+s})}return r.sort((e,t)=>t.score-e.score).slice(0,o).map(e=>e.name)}export function analyzeFunction(e,t,n=3,o=3){const r=e.functions.get(t);if(!(void 0!==r)){return{targetFunction:t,found:!1,upstream:{},downstream:{},similarFunctions:findSimilarFunctions(e,t)}}return{targetFunction:t,found:!0,upstream:getUpstreamTrace(e,t,n),downstream:getDownstreamTrace(e,t,o),functionInfo:r}}