// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mindsdb

import (
	"bytes"
	"context"
	"database/sql"
	"fmt"
	"net/http"
	"os"
	"regexp"
	"strings"
	"testing"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/google/uuid"
	"github.com/googleapis/genai-toolbox/internal/testutils"
	"github.com/googleapis/genai-toolbox/tests"
)

var (
	MindsDBSourceKind = "mindsdb"
	MindsDBToolKind   = "mindsdb-sql"
	MindsDBDatabase   = os.Getenv("MINDSDB_DATABASE")
	MindsDBHost       = os.Getenv("MINDSDB_HOST")
	MindsDBPort       = os.Getenv("MINDSDB_PORT")
	MindsDBUser       = os.Getenv("MINDSDB_USER")
	MindsDBPass       = os.Getenv("MINDSDB_PASS")
)

func getMindsDBVars(t *testing.T) map[string]any {
	switch "" {
	case MindsDBDatabase:
		t.Fatal("'MINDSDB_DATABASE' not set")
	case MindsDBHost:
		t.Fatal("'MINDSDB_HOST' not set")
	case MindsDBPort:
		t.Fatal("'MINDSDB_PORT' not set")
	case MindsDBUser:
		t.Fatal("'MINDSDB_USER' not set")
	}

	// MindsDBPass can be empty, but the env var must exist
	if _, exists := os.LookupEnv("MINDSDB_PASS"); !exists {
		t.Fatal("'MINDSDB_PASS' not set (can be empty)")
	}

	// Handle no-password authentication
	mindsdbPassword := MindsDBPass
	if mindsdbPassword == "none" {
		mindsdbPassword = ""
	}

	return map[string]any{
		"kind":     MindsDBSourceKind,
		"host":     MindsDBHost,
		"port":     MindsDBPort,
		"database": MindsDBDatabase,
		"user":     MindsDBUser,
		"password": mindsdbPassword,
	}
}

// initMindsDBConnectionPool creates a connection pool using MySQL protocol
func initMindsDBConnectionPool(host, port, user, pass, dbname string) (*sql.DB, error) {
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", user, pass, host, port, dbname)
	pool, err := sql.Open("mysql", dsn)
	if err != nil {
		return nil, fmt.Errorf("sql.Open: %w", err)
	}
	return pool, nil
}

func TestMindsDBToolEndpoints(t *testing.T) {
	sourceConfig := getMindsDBVars(t)
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
	defer cancel()

	var args []string

	// Create unique table names with UUID
	tableNameParam := "param_table_" + strings.ReplaceAll(uuid.New().String(), "-", "")
	tableNameAuth := "auth_table_" + strings.ReplaceAll(uuid.New().String(), "-", "")
	// Tool statements with ORDER BY for consistent results
	paramToolStmt := fmt.Sprintf("SELECT * FROM files.%s WHERE id = ? OR name = ? ORDER BY id", tableNameParam)
	idParamToolStmt := fmt.Sprintf("SELECT * FROM files.%s WHERE id = ? ORDER BY id", tableNameParam)
	nameParamToolStmt := fmt.Sprintf("SELECT * FROM files.%s WHERE name = ? ORDER BY id", tableNameParam)
	authToolStmt := fmt.Sprintf("SELECT name FROM files.%s WHERE email = ? ORDER BY name", tableNameAuth)

	toolsFile := map[string]any{
		"sources": map[string]any{
			"my-instance": sourceConfig,
		},
		"authServices": map[string]any{
			"my-google-auth": map[string]any{
				"kind":     "google",
				"clientId": tests.ClientId,
			},
		},
		"tools": map[string]any{
			"my-simple-tool": map[string]any{
				"kind":        MindsDBToolKind,
				"source":      "my-instance",
				"description": "Simple tool to test end to end functionality.",
				"statement":   "SELECT 1",
			},
			"my-tool": map[string]any{
				"kind":        MindsDBToolKind,
				"source":      "my-instance",
				"description": "Tool to test invocation with params.",
				"statement":   paramToolStmt,
				"parameters": []map[string]any{
					{
						"name":        "id",
						"type":        "integer",
						"description": "user ID",
					},
					{
						"name":        "name",
						"type":        "string",
						"description": "user name",
					},
				},
			},
			"my-tool-by-id": map[string]any{
				"kind":        MindsDBToolKind,
				"source":      "my-instance",
				"description": "Tool to test invocation with params.",
				"statement":   idParamToolStmt,
				"parameters": []map[string]any{
					{
						"name":        "id",
						"type":        "integer",
						"description": "user ID",
					},
				},
			},
			"my-tool-by-name": map[string]any{
				"kind":        MindsDBToolKind,
				"source":      "my-instance",
				"description": "Tool to test invocation with params.",
				"statement":   nameParamToolStmt,
				"parameters": []map[string]any{
					{
						"name":        "name",
						"type":        "string",
						"description": "user name",
						"required":    false,
					},
				},
			},
			"my-array-tool": map[string]any{
				"kind":        MindsDBToolKind,
				"source":      "my-instance",
				"description": "Tool to test invocation with array params.",
				"statement":   "SELECT 1 as id, 'Alice' as name UNION SELECT 3 as id, 'Sid' as name",
			},
			"my-auth-tool": map[string]any{
				"kind":        MindsDBToolKind,
				"source":      "my-instance",
				"description": "Tool to test authenticated parameters.",
				"statement":   authToolStmt,
				"parameters": []map[string]any{
					{
						"name":        "email",
						"type":        "string",
						"description": "user email",
						"authServices": []map[string]string{
							{
								"name":  "my-google-auth",
								"field": "email",
							},
						},
					},
				},
			},
			"my-auth-required-tool": map[string]any{
				"kind":        MindsDBToolKind,
				"source":      "my-instance",
				"description": "Tool to test auth required invocation.",
				"statement":   "SELECT 1",
				"authRequired": []string{
					"my-google-auth",
				},
			},
			"my-fail-tool": map[string]any{
				"kind":        MindsDBToolKind,
				"source":      "my-instance",
				"description": "Tool to test statement with incorrect syntax.",
				"statement":   "INVALID SQL STATEMENT",
			},
			"my-exec-sql-tool": map[string]any{
				"kind":        "mindsdb-execute-sql",
				"source":      "my-instance",
				"description": "Tool to execute sql",
			},
			"my-auth-exec-sql-tool": map[string]any{
				"kind":        "mindsdb-execute-sql",
				"source":      "my-instance",
				"description": "Tool to execute sql with auth",
				"authRequired": []string{
					"my-google-auth",
				},
			},
		},
	}

	cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...)
	if err != nil {
		t.Fatalf("command initialization returned an error: %s", err)
	}
	defer cleanup()

	waitCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
	defer cancel()
	out, err := testutils.WaitForString(waitCtx, regexp.MustCompile(`Server ready to serve`), cmd.Out)
	if err != nil {
		t.Logf("toolbox command logs: \n%s", out)
		t.Fatalf("toolbox didn't start successfully: %s", err)
	}

	// Create connection pool and test tables with sample data
	pool, err := initMindsDBConnectionPool(MindsDBHost, MindsDBPort, MindsDBUser, MindsDBPass, MindsDBDatabase)
	if err != nil {
		t.Fatalf("unable to create MindsDB connection pool: %s", err)
	}
	defer pool.Close()

	// Create param table: id=1:Alice, id=2:Jane, id=3:Sid, id=4:null
	createParamSQL := fmt.Sprintf("CREATE TABLE files.%s (SELECT 1 as id, 'Alice' as name UNION ALL SELECT 2, 'Jane' UNION ALL SELECT 3, 'Sid' UNION ALL SELECT 4, NULL)", tableNameParam)
	_, err = pool.ExecContext(ctx, createParamSQL)
	if err != nil {
		t.Fatalf("unable to create param table: %s", err)
	}

	// Create auth table: id=1:Alice:test@..., id=2:Jane:jane@...
	createAuthSQL := fmt.Sprintf("CREATE TABLE files.%s (SELECT 1 as id, 'Alice' as name, '%s' as email UNION ALL SELECT 2, 'Jane', 'janedoe@gmail.com')", tableNameAuth, tests.ServiceAccountEmail)
	_, err = pool.ExecContext(ctx, createAuthSQL)
	if err != nil {
		t.Fatalf("unable to create auth table: %s", err)
	}

	defer func() {
		_, _ = pool.ExecContext(ctx, fmt.Sprintf("DROP TABLE IF EXISTS files.%s", tableNameParam))
		_, _ = pool.ExecContext(ctx, fmt.Sprintf("DROP TABLE IF EXISTS files.%s", tableNameAuth))
	}()

	select1Want := "[{\"1\":1}]"

	// Run standard tool tests with MindsDB-specific expectations
	tests.RunToolGetTest(t)
	tests.RunToolInvokeTest(t, select1Want,
		tests.DisableArrayTest(), // MindsDB doesn't support array parameters
	)

	t.Run("mindsdb_core_functionality", func(t *testing.T) {
		tests.RunToolInvokeSimpleTest(t, "my-simple-tool", select1Want)
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool", []byte(`{"sql": "SELECT 1"}`), select1Want)
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool", []byte(`{"sql": "SELECT 1+1 as result"}`), "[{\"result\":2}]")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool", []byte(`{"sql": "SELECT 'hello' as greeting"}`), "[{\"greeting\":\"hello\"}]")
	})

	t.Run("mindsdb_sql_tests", func(t *testing.T) {
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool", []byte(`{"sql": "SELECT 1"}`), select1Want)
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool", []byte(`{"sql": "SHOW DATABASES"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool", []byte(`{"sql": "SHOW TABLES"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool", []byte(`{"sql": "SELECT TABLE_NAME FROM information_schema.TABLES LIMIT 1"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool", []byte(`{"sql": "SELECT 1+1 as result"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool", []byte(`{"sql": "SELECT UPPER('hello') as result"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool", []byte(`{"sql": "SELECT NOW() as current_time"}`), "")
	})

	// Test CREATE DATABASE (MindsDB's federated database capability)
	t.Run("mindsdb_create_database", func(t *testing.T) {
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP DATABASE IF EXISTS test_postgres_db"}`), "")

		// Create external database integration using MindsDB's demo database
		createDBSQL := `CREATE DATABASE test_postgres_db WITH ENGINE = 'postgres', PARAMETERS = {'user': 'demo_user', 'password': 'demo_password', 'host': 'samples.mindsdb.com', 'port': '5432', 'database': 'demo', 'schema': 'demo_data'}`
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "`+createDBSQL+`"}`), "")

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "SHOW DATABASES"}`), "")

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "SHOW TABLES FROM test_postgres_db"}`), "")

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP DATABASE IF EXISTS test_postgres_db"}`), "")
	})

	// Test MindsDB integration capabilities with product/review data
	t.Run("mindsdb_integration_demo", func(t *testing.T) {
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_products"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_reviews"}`), "")

		// Create test tables with sample data
		createProductsSQL := `CREATE TABLE files.test_products (SELECT 'PROD001' as product_id, 'Laptop Computer' as product_name, 'Electronics' as category UNION ALL SELECT 'PROD002', 'Office Chair', 'Furniture' UNION ALL SELECT 'PROD003', 'Coffee Maker', 'Appliances' UNION ALL SELECT 'PROD004', 'Desk Lamp', 'Furniture')`
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "`+createProductsSQL+`"}`), "")

		createReviewsSQL := `CREATE TABLE files.test_reviews (SELECT 'PROD001' as product_id, 'Great laptop, very fast!' as review, 5 as rating UNION ALL SELECT 'PROD001', 'Good value for money', 4 UNION ALL SELECT 'PROD002', 'Very comfortable chair', 5 UNION ALL SELECT 'PROD002', 'Nice design but expensive', 3 UNION ALL SELECT 'PROD003', 'Makes excellent coffee', 5 UNION ALL SELECT 'PROD004', 'Bright light, perfect for reading', 4)`
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "`+createReviewsSQL+`"}`), "")

		t.Run("query_created_tables", func(t *testing.T) {
			tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
				[]byte(`{"sql": "SELECT * FROM files.test_products ORDER BY product_id"}`), "")
			tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
				[]byte(`{"sql": "SELECT * FROM files.test_reviews ORDER BY product_id, rating DESC"}`), "")
			tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
				[]byte(`{"sql": "SELECT category, COUNT(*) as product_count FROM files.test_products GROUP BY category ORDER BY category"}`), "")
			tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
				[]byte(`{"sql": "SELECT product_id, AVG(rating) as avg_rating FROM files.test_reviews GROUP BY product_id ORDER BY avg_rating DESC"}`), "")
		})

		t.Run("cross_database_join", func(t *testing.T) {
			joinSQL := `SELECT p.product_name, p.category, r.review, r.rating FROM files.test_products p JOIN files.test_reviews r ON p.product_id = r.product_id WHERE r.rating >= 4 ORDER BY p.product_name, r.rating DESC`
			tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
				[]byte(`{"sql": "`+joinSQL+`"}`), "")

			aggSQL := `SELECT p.category, COUNT(DISTINCT p.product_id) as product_count, COUNT(r.review) as review_count, AVG(r.rating) as avg_rating FROM files.test_products p LEFT JOIN files.test_reviews r ON p.product_id = r.product_id GROUP BY p.category ORDER BY avg_rating DESC`
			tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
				[]byte(`{"sql": "`+aggSQL+`"}`), "")
		})

		t.Run("advanced_sql_features", func(t *testing.T) {
			subquerySQL := `SELECT p.product_name, p.category, AVG(r.rating) as avg_rating FROM files.test_products p JOIN files.test_reviews r ON p.product_id = r.product_id GROUP BY p.product_id, p.product_name, p.category HAVING AVG(r.rating) >= 4 ORDER BY avg_rating DESC`
			tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
				[]byte(`{"sql": "`+subquerySQL+`"}`), "")

			caseSQL := `SELECT product_id, review, rating, CASE WHEN rating >= 5 THEN 'Excellent' WHEN rating >= 4 THEN 'Good' WHEN rating >= 3 THEN 'Average' ELSE 'Poor' END as rating_category FROM files.test_reviews ORDER BY rating DESC, product_id`
			tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
				[]byte(`{"sql": "`+caseSQL+`"}`), "")
		})

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_product_summary"}`), "")

		t.Run("data_manipulation", func(t *testing.T) {
			summarySQL := `CREATE TABLE files.test_product_summary (SELECT p.product_id, p.product_name, p.category, COUNT(r.review) as total_reviews, AVG(r.rating) as avg_rating, MAX(r.rating) as max_rating, MIN(r.rating) as min_rating FROM files.test_products p LEFT JOIN files.test_reviews r ON p.product_id = r.product_id GROUP BY p.product_id, p.product_name, p.category)`
			tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
				[]byte(`{"sql": "`+summarySQL+`"}`), "")

			tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
				[]byte(`{"sql": "SELECT * FROM files.test_product_summary ORDER BY avg_rating DESC"}`), "")
		})

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_products"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_reviews"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_product_summary"}`), "")
	})

	// Test database integration and cross-database joins
	t.Run("mindsdb_create_database_integration", func(t *testing.T) {
		showDBSQL := `SHOW DATABASES`
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "`+showDBSQL+`"}`), "")

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "SHOW TABLES FROM files"}`), "")

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_integration_data"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_local_data"}`), "")

		createIntegrationTableSQL := `CREATE TABLE files.test_integration_data (SELECT 1 as id, 'Data from integration' as description, CURDATE() as created_at UNION ALL SELECT 2, 'Another record', CURDATE() UNION ALL SELECT 3, 'Third record', CURDATE())`
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "`+createIntegrationTableSQL+`"}`), "")

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "SELECT * FROM files.test_integration_data ORDER BY id"}`), "")

		createLocalTableSQL := `CREATE TABLE files.test_local_data (SELECT 1 as id, 'Local metadata' as metadata UNION ALL SELECT 2, 'More metadata')`
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "`+createLocalTableSQL+`"}`), "")

		crossJoinSQL := `SELECT i.id, i.description, l.metadata FROM files.test_integration_data i LEFT JOIN files.test_local_data l ON i.id = l.id ORDER BY i.id`
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "`+crossJoinSQL+`"}`), "")

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_integration_data"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_local_data"}`), "")
	})

	// Test data transformation with customer order data
	t.Run("mindsdb_data_transformation", func(t *testing.T) {
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_orders"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_customer_summary"}`), "")

		createOrdersSQL := `CREATE TABLE files.test_orders (SELECT 1 as order_id, 'CUST001' as customer_id, 100.50 as amount, '2024-01-15' as order_date UNION ALL SELECT 2, 'CUST001', 250.00, '2024-02-20' UNION ALL SELECT 3, 'CUST002', 75.25, '2024-01-18' UNION ALL SELECT 4, 'CUST003', 500.00, '2024-03-10' UNION ALL SELECT 5, 'CUST002', 150.00, '2024-02-25')`
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "`+createOrdersSQL+`"}`), "")

		customerSummarySQL := `CREATE TABLE files.test_customer_summary (SELECT customer_id, COUNT(*) as total_orders, SUM(amount) as total_spent, AVG(amount) as avg_order_value, MIN(order_date) as first_order_date, MAX(order_date) as last_order_date FROM files.test_orders GROUP BY customer_id)`
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "`+customerSummarySQL+`"}`), "")

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "SELECT * FROM files.test_customer_summary ORDER BY total_spent DESC"}`), "")

		segmentSQL := `SELECT customer_id, total_spent, CASE WHEN total_spent >= 300 THEN 'High Value' WHEN total_spent >= 150 THEN 'Medium Value' ELSE 'Low Value' END as customer_segment FROM files.test_customer_summary ORDER BY total_spent DESC`
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "`+segmentSQL+`"}`), "")

		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_orders"}`), "")
		tests.RunToolInvokeParametersTest(t, "my-exec-sql-tool",
			[]byte(`{"sql": "DROP TABLE IF EXISTS files.test_customer_summary"}`), "")
	})

	// Test error handling - these are expected to fail but exercise error paths
	t.Run("mindsdb_error_handling", func(t *testing.T) {
		// Test invalid SQL - expect this to fail with 400
		resp, err := http.Post("http://127.0.0.1:5000/api/tool/my-exec-sql-tool/invoke", "application/json", bytes.NewBuffer([]byte(`{"sql": "INVALID SQL QUERY"}`)))
		if err != nil {
			t.Fatalf("error when sending request: %s", err)
		}
		defer resp.Body.Close()
		if resp.StatusCode != http.StatusBadRequest {
			t.Logf("Expected 400 for invalid SQL, got %d (this exercises error handling)", resp.StatusCode)
		}

		// Test empty SQL - expect this to fail with 400
		resp2, err := http.Post("http://127.0.0.1:5000/api/tool/my-exec-sql-tool/invoke", "application/json", bytes.NewBuffer([]byte(`{"sql": ""}`)))
		if err != nil {
			t.Fatalf("error when sending request: %s", err)
		}
		defer resp2.Body.Close()
		if resp2.StatusCode != http.StatusBadRequest {
			t.Logf("Expected 400 for empty SQL, got %d (this exercises error handling)", resp2.StatusCode)
		}
	})

	// Test authentication - these are expected to fail but exercise auth code paths
	t.Run("mindsdb_auth_tests", func(t *testing.T) {
		// Test auth-required tool without auth - expect this to fail with 401
		resp, err := http.Post("http://127.0.0.1:5000/api/tool/my-auth-exec-sql-tool/invoke", "application/json", bytes.NewBuffer([]byte(`{"sql": "SELECT 1"}`)))
		if err != nil {
			t.Fatalf("error when sending request: %s", err)
		}
		defer resp.Body.Close()
		if resp.StatusCode != http.StatusUnauthorized {
			t.Logf("Expected 401 for missing auth, got %d (this exercises auth handling)", resp.StatusCode)
		}
	})
}
