I haven't tested it but it should give you a pretty good idea on how to set this up.

    public function actionTest() {
        $entryQuery = Entry::find()->section('mySection');
    
        // All the element relations. For example tags and categories.
        $myArrayWithTags = [/* ... */];
        $myArrayWithCategories = [/* ... */];
        $allRelations = array_merge($myArrayWithTags, $myArrayWithCategories);
    
        // Filter by relations
        $this->_applyRelationFilter($entryQuery, $allRelations);
    
        // Filter by custom fields
        $this->_applyFieldFilter($entryQuery, 'myRadioField', 'value2');
        $this->_applyFieldFilter($entryQuery, 'myNumberField', 3);
        $this->_applyFieldFilter($entryQuery, 'myCheckboxField', true);
    
        // Build response string
        $content = "Entries:<br>";
        $content .= "<pre>" . json_encode($entryQuery->all()) . "</pre>";
    
        // Respond
        $response = Craft::$app->getResponse();
        $response->content = $content;
        return $response;
    }
    
    private function _applyRelationFilter(ElementQuery $query, array $elements) : array {
        $relatedTo = [];
    
        // Build the list of relations in the correct format
        foreach($elements as $element) {
            array_push($relatedTo, [
                "targetElement" => $element
            ]);
        }
    
        // Create an array with and as the first value so 
        // the result only contains elements that have all the set relations
        $relatedTo = array_merge(['and'], $relatedTo);
    
        // Set query relatedTo
        return $query->relatedTo($relatedTo);
    }
    
    private function _applyFieldFilter(ElementQuery $query, string $handle, $value) {
        $query->andWhere([
            ('content.field_' . $handle) => $value
        ]);
    }