// Nexus Tools — File, shell, and search operations
// Aislinn McCubbins, April 2026

fn tool_read(path: String) -> String {
    let content = read_file(path)
    if starts_with(content, "error:") {
        return content
    }
    // Add line numbers
    let lines = str_lines(content)
    let result = ""
    let i = 0
    while i < array_len(lines) {
        let line_nr = int_to_str(i + 1)
        // Pad line number
        while str_len(line_nr) < 4 {
            line_nr = " " + line_nr
        }
        result = result + line_nr + " | " + array_get(lines, i) + "\n"
        i = i + 1
    }
    return result
}

fn tool_write(path: String, content: String) -> String {
    let result = write_file(path, content)
    if starts_with(result, "error:") {
        return result
    }
    return "Wrote " + int_to_str(str_len(content)) + " bytes to " + path
}

fn tool_edit(path: String, old_text: String, new_text: String) -> String {
    let content = read_file(path)
    if starts_with(content, "error:") {
        return "Error: could not read " + path
    }
    if str_contains(content, old_text) == false {
        return "Error: old_text not found in " + path
    }
    let updated = str_replace(content, old_text, new_text)
    let result = write_file(path, updated)
    if starts_with(result, "error:") {
        return result
    }
    return "Edited " + path + " — replaced " + int_to_str(str_len(old_text)) + " chars"
}

fn tool_bash(command: String) -> String {
    // Safety: wrap with timeout
    let safe_cmd = "timeout 60 " + command
    let result = shell_exec(safe_cmd)
    if str_len(result) > 4000 {
        // Truncate long output
        result = str_slice(result, 0, 4000) + "\n... (truncated)"
    }
    return result
}

fn tool_grep(pattern: String, path: String) -> String {
    let cmd = "grep -rn \"" + pattern + "\" " + path + " 2>/dev/null | head -30"
    return shell_exec(cmd)
}

fn tool_find(pattern: String, path: String) -> String {
    let cmd = "find " + path + " -name \"" + pattern + "\" -type f 2>/dev/null | head -20"
    return shell_exec(cmd)
}

// Parse tool calls from LLM response
// Format: <tool_call>tool_name|arg1|arg2|arg3</tool_call>
// Or JSON-ish: <tool_call>{"tool":"name","args":{"path":"x"}}</tool_call>
fn parse_tool_call(text: String) -> Array {
    // Returns: [tool_name, arg1, arg2, arg3] or empty array if no tool call

    let start = str_find(text, "<tool_call>")
    if start < 0 {
        return array_new()
    }

    let after_tag = start + 11
    let end = str_find(text, "</tool_call>")
    if end < 0 {
        end = str_len(text)
    }

    let call_body = str_trim(str_slice(text, after_tag, end))

    // Try simple pipe format first: tool_name|arg1|arg2
    if str_contains(call_body, "|") {
        return str_split(call_body, "|")
    }

    // Try JSON format: {"tool":"name","args":{"key":"val"}}
    let tool_name = ""
    let tool_pos = str_find(call_body, "\"tool\"")
    if tool_pos >= 0 {
        let colon = str_find(str_slice(call_body, tool_pos, str_len(call_body)), ":")
        if colon >= 0 {
            let rest = str_slice(call_body, tool_pos + colon + 1, str_len(call_body))
            let q1 = str_find(rest, "\"")
            if q1 >= 0 {
                let rest2 = str_slice(rest, q1 + 1, str_len(rest))
                let q2 = str_find(rest2, "\"")
                if q2 >= 0 {
                    tool_name = str_slice(rest2, 0, q2)
                }
            }
        }
    }

    if str_len(tool_name) == 0 {
        return array_new()
    }

    // Extract first arg (usually "path" or "command")
    let result = array_new()
    result = array_push(result, tool_name)

    // Look for common arg keys
    let arg_keys = array_new()
    arg_keys = array_push(arg_keys, "path")
    arg_keys = array_push(arg_keys, "command")
    arg_keys = array_push(arg_keys, "pattern")
    arg_keys = array_push(arg_keys, "content")
    arg_keys = array_push(arg_keys, "old_text")
    arg_keys = array_push(arg_keys, "new_text")

    let k = 0
    while k < array_len(arg_keys) {
        let key = array_get(arg_keys, k)
        let key_pattern = "\"" + key + "\""
        let kpos = str_find(call_body, key_pattern)
        if kpos >= 0 {
            let after_key = str_slice(call_body, kpos + str_len(key_pattern), str_len(call_body))
            let colon = str_find(after_key, ":")
            if colon >= 0 {
                let after_colon = str_trim(str_slice(after_key, colon + 1, str_len(after_key)))
                if starts_with(after_colon, "\"") {
                    let val_start = str_slice(after_colon, 1, str_len(after_colon))
                    let q = str_find(val_start, "\"")
                    if q >= 0 {
                        result = array_push(result, str_slice(val_start, 0, q))
                    }
                }
            }
        }
        k = k + 1
    }

    return result
}

fn execute_tool(call: Array) -> String {
    let tool_name = array_get(call, 0)
    let arg1 = ""
    let arg2 = ""
    let arg3 = ""
    if array_len(call) > 1 { arg1 = array_get(call, 1) }
    if array_len(call) > 2 { arg2 = array_get(call, 2) }
    if array_len(call) > 3 { arg3 = array_get(call, 3) }

    if str_eq(tool_name, "read_file") {
        return tool_read(arg1)
    }
    if str_eq(tool_name, "write_file") {
        return tool_write(arg1, arg2)
    }
    if str_eq(tool_name, "edit_file") {
        return tool_edit(arg1, arg2, arg3)
    }
    if str_eq(tool_name, "bash") {
        return tool_bash(arg1)
    }
    if str_eq(tool_name, "grep") {
        return tool_grep(arg1, arg2)
    }
    if str_eq(tool_name, "search") {
        return tool_find(arg1, arg2)
    }

    return "Unknown tool: " + tool_name
}
