package tools

import (
	"context"
	"os"
	"testing"

	"git.yeij.top/AskaEth/Cyrene/ai-core/internal/host"
	"git.yeij.top/AskaEth/Cyrene/ai-core/internal/rag"
)

func TestHostExecToolDefinition(t *testing.T) {
	cfg := host.DefaultSandboxConfig()
	cfg.AllowedDirs = []string{os.TempDir()}
	sandbox := host.NewSandbox(cfg)
	mgr := host.NewManager(host.NewDirectBackend(sandbox))

	tool := NewHostExecTool(mgr)
	def := tool.Definition()
	if def.Name != "host_exec" {
		t.Fatalf("unexpected name: %s", def.Name)
	}
	t.Logf("host_exec definition OK")

	// Test execute with echo
	result, err := tool.Execute(context.Background(), map[string]interface{}{
		"command": "echo test-ok",
	})
	if err != nil {
		t.Fatalf("execute error: %v", err)
	}
	if !result.Success {
		t.Fatalf("execute failed: %s", result.Error)
	}
	t.Logf("host_exec execute OK: data=%s", result.Data[:50])
}

func TestHostFileToolDefinition(t *testing.T) {
	cfg := host.DefaultSandboxConfig()
	tmpDir := os.TempDir()
	cfg.AllowedDirs = []string{tmpDir}
	sandbox := host.NewSandbox(cfg)
	mgr := host.NewManager(host.NewDirectBackend(sandbox))
	mgr.SetAllowedDirs([]string{tmpDir})

	tool := NewHostFileTool(mgr)
	def := tool.Definition()
	if def.Name != "host_file" {
		t.Fatalf("unexpected name: %s", def.Name)
	}
	t.Logf("host_file definition OK")

	// Test list
	result, err := tool.Execute(context.Background(), map[string]interface{}{
		"action": "list",
		"path":   tmpDir,
	})
	if err != nil {
		t.Fatalf("list execute error: %v", err)
	}
	if !result.Success {
		t.Fatalf("list failed: %s", result.Error)
	}
	t.Logf("host_file list OK: data len=%d", len(result.Data))
}

func TestHostSystemToolDefinition(t *testing.T) {
	cfg := host.DefaultSandboxConfig()
	sandbox := host.NewSandbox(cfg)
	mgr := host.NewManager(host.NewDirectBackend(sandbox))

	tool := NewHostSystemTool(mgr)
	def := tool.Definition()
	if def.Name != "host_system" {
		t.Fatalf("unexpected name: %s", def.Name)
	}
	t.Logf("host_system definition OK")

	result, err := tool.Execute(context.Background(), map[string]interface{}{})
	if err != nil {
		t.Fatalf("execute error: %v", err)
	}
	if !result.Success {
		t.Fatalf("execute failed: %s", result.Error)
	}
	t.Logf("host_system execute OK: data len=%d", len(result.Data))
}

type testEmbedder struct{}

func (e *testEmbedder) Embed(ctx context.Context, text string) ([]float64, error) {
	n := float64(len([]rune(text)))
	v := make([]float64, 128)
	for _, r := range text {
		v[int(r)%128] += 1.0 / n
	}
	return v, nil
}

func (e *testEmbedder) EmbedBatch(ctx context.Context, texts []string) ([]float64, error) {
	combined := ""
	for _, t := range texts {
		combined += t
	}
	return e.Embed(ctx, combined)
}

func (e *testEmbedder) IsAvailable() bool { return true }

func TestKnowledgeSearchToolDefinition(t *testing.T) {
	store := rag.NewKnowledgeStore(&testEmbedder{}, os.TempDir())
	retriever := rag.NewRetriever(store)

	tool := NewKnowledgeSearchTool(retriever)
	def := tool.Definition()
	if def.Name != "knowledge_search" {
		t.Fatalf("unexpected name: %s", def.Name)
	}
	t.Logf("knowledge_search definition OK")

	result, err := tool.Execute(context.Background(), map[string]interface{}{
		"query": "test query",
	})
	if err != nil {
		t.Fatalf("execute error: %v", err)
	}
	if !result.Success {
		t.Fatalf("execute failed: %s", result.Error)
	}
	t.Logf("knowledge_search execute OK: data=%s", result.Data[:80])
}

func TestKnowledgeIngestToolDefinition(t *testing.T) {
	store := rag.NewKnowledgeStore(&testEmbedder{}, os.TempDir())

	tool := NewKnowledgeIngestTool(store)
	def := tool.Definition()
	if def.Name != "knowledge_ingest" {
		t.Fatalf("unexpected name: %s", def.Name)
	}
	t.Logf("knowledge_ingest definition OK")
}
