package mcp

import (
	"math"
	"strings"
	"testing"
)

func TestEvalArith(t *testing.T) {
	cases := map[string]float64{
		"1+2*3":     7,
		"(1+2)*3":   9,
		"2^3^2":     512, // 右结合
		"-3+5":      2,
		"10/4":      2.5,
		"10%3":      1,
		"2*(3+4)-5": 9,
		"-(2+3)*2":  -10,
		"3.5e1+0.5": 35.5,
	}
	for in, want := range cases {
		got, err := evalArith(in)
		if err != nil {
			t.Errorf("evalArith(%q) 报错: %v", in, err)
			continue
		}
		if math.Abs(got-want) > 1e-9 {
			t.Errorf("evalArith(%q)=%v want %v", in, got, want)
		}
	}
}

func TestEvalArithErrors(t *testing.T) {
	for _, in := range []string{"1/0", "1+", "(1+2", "1+2)", "rm -rf /", "import os", ""} {
		if _, err := evalArith(in); err == nil {
			t.Errorf("evalArith(%q) 应报错但没有", in)
		}
	}
}

func TestHTMLToText(t *testing.T) {
	in := `<html><head><title>x</title></head><body><script>alert(1)</script>
	<h1>标题</h1><p>第一段&amp;符号</p><style>.a{}</style><div>第二段</div></body></html>`
	got := htmlToText(in)
	if strings.Contains(got, "alert") || strings.Contains(got, ".a{}") {
		t.Fatalf("脚本/样式未剔除: %q", got)
	}
	if !strings.Contains(got, "标题") || !strings.Contains(got, "第一段&符号") || !strings.Contains(got, "第二段") {
		t.Fatalf("正文/实体提取不正确: %q", got)
	}
}

func TestDDGUnwrap(t *testing.T) {
	got := ddgUnwrap("//duckduckgo.com/l/?uddg=https%3A%2F%2Fexample.com%2Fa&rut=x")
	if got != "https://example.com/a" {
		t.Fatalf("ddgUnwrap 解码错误: %q", got)
	}
}

func TestValidateReadOnlySQL(t *testing.T) {
	okCases := []string{
		"SELECT 1",
		"select count(*) from sundynix_task",
		"WITH x AS (SELECT 1) SELECT * FROM x",
		"  select * from t where created_at > now()  ", // created/update 作为列名一部分不应误伤
	}
	for _, q := range okCases {
		if _, ok := validateReadOnlySQL(q); !ok {
			t.Errorf("应通过: %q", q)
		}
	}
	badCases := []string{
		"insert into t values (1)",
		"update t set a=1",
		"delete from t",
		"drop table t",
		"select 1; drop table t",
		"truncate t",
		"SELECT 1; SELECT 2",
		"grant all on t to x",
	}
	for _, q := range badCases {
		if _, ok := validateReadOnlySQL(q); ok {
			t.Errorf("应拒绝: %q", q)
		}
	}
}
