package tools

import (
	"context"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"
)

func TestMemoryWriteToolNamespaceIsolation(t *testing.T) {
	t.Parallel()

	workspace := t.TempDir()
	tool := NewMemoryWriteTool(workspace)

	_, err := tool.Execute(context.Background(), map[string]interface{}{
		"content":   "main note",
		"kind":      "daily",
		"namespace": "main",
	})
	if err != nil {
		t.Fatalf("main write failed: %v", err)
	}

	_, err = tool.Execute(context.Background(), map[string]interface{}{
		"content":   "coder note",
		"kind":      "daily",
		"namespace": "coder",
	})
	if err != nil {
		t.Fatalf("namespace write failed: %v", err)
	}

	today := time.Now().Format("2006-01-02") + ".md"
	mainPath := filepath.Join(workspace, "memory", today)
	coderPath := filepath.Join(workspace, "agents", "coder", "memory", today)

	mainData, err := os.ReadFile(mainPath)
	if err != nil {
		t.Fatalf("read main daily file failed: %v", err)
	}
	if !strings.Contains(string(mainData), "main note") {
		t.Fatalf("main daily memory missing expected content: %s", string(mainData))
	}

	coderData, err := os.ReadFile(coderPath)
	if err != nil {
		t.Fatalf("read namespaced daily file failed: %v", err)
	}
	if !strings.Contains(string(coderData), "coder note") {
		t.Fatalf("namespaced daily memory missing expected content: %s", string(coderData))
	}
}

func TestMemorySearchToolNamespaceIsolation(t *testing.T) {
	t.Parallel()

	workspace := t.TempDir()
	write := NewMemoryWriteTool(workspace)
	search := NewMemorySearchTool(workspace)

	_, _ = write.Execute(context.Background(), map[string]interface{}{
		"content":    "main_unique_keyword_123",
		"kind":       "longterm",
		"importance": "high",
		"namespace":  "main",
	})
	_, _ = write.Execute(context.Background(), map[string]interface{}{
		"content":    "coder_unique_keyword_456",
		"kind":       "longterm",
		"importance": "high",
		"namespace":  "coder",
	})

	mainRes, err := search.Execute(context.Background(), map[string]interface{}{
		"query":      "main_unique_keyword_123",
		"namespace":  "main",
		"maxResults": float64(3),
	})
	if err != nil {
		t.Fatalf("main namespace search failed: %v", err)
	}
	if !strings.Contains(mainRes, "main_unique_keyword_123") {
		t.Fatalf("expected main namespace result to include keyword, got: %s", mainRes)
	}

	coderRes, err := search.Execute(context.Background(), map[string]interface{}{
		"query":      "coder_unique_keyword_456",
		"namespace":  "coder",
		"maxResults": float64(3),
	})
	if err != nil {
		t.Fatalf("coder namespace search failed: %v", err)
	}
	if !strings.Contains(coderRes, "coder_unique_keyword_456") {
		t.Fatalf("expected coder namespace result to include keyword, got: %s", coderRes)
	}
	if strings.Contains(coderRes, "main_unique_keyword_123") {
		t.Fatalf("namespace isolation violated, coder search leaked main data: %s", coderRes)
	}
}

func TestParseMemoryNamespaceArgUsesHelper(t *testing.T) {
	t.Parallel()

	if got := parseMemoryNamespaceArg(map[string]interface{}{"namespace": "Coder Agent"}); got != "coder-agent" {
		t.Fatalf("unexpected namespace parse result: %q", got)
	}
	if got := parseMemoryNamespaceArg(nil); got != "main" {
		t.Fatalf("expected main namespace for nil args, got %q", got)
	}
}
