package tools

import (
	"context"
	"strings"

	"github.com/modelcontextprotocol/go-sdk/mcp"

	"git.warky.dev/wdevs/amcs/internal/ai"
	"git.warky.dev/wdevs/amcs/internal/config"
	"git.warky.dev/wdevs/amcs/internal/session"
	"git.warky.dev/wdevs/amcs/internal/store"
	thoughttypes "git.warky.dev/wdevs/amcs/internal/types"
)

type SearchTool struct {
	store      *store.DB
	embeddings *ai.EmbeddingRunner
	search     config.SearchConfig
	sessions   *session.ActiveProjects
}

type SearchInput struct {
	Query     string  `json:"query" jsonschema:"the semantic query to search for"`
	Limit     int     `json:"limit,omitempty" jsonschema:"maximum number of results to return"`
	Threshold float64 `json:"threshold,omitempty" jsonschema:"minimum similarity threshold between 0 and 1"`
	Project   string  `json:"project,omitempty" jsonschema:"optional project name or id to scope the search"`
}

type SearchOutput struct {
	Results []thoughttypes.SearchResult `json:"results"`
}

func NewSearchTool(db *store.DB, embeddings *ai.EmbeddingRunner, search config.SearchConfig, sessions *session.ActiveProjects) *SearchTool {
	return &SearchTool{store: db, embeddings: embeddings, search: search, sessions: sessions}
}

func (t *SearchTool) Handle(ctx context.Context, req *mcp.CallToolRequest, in SearchInput) (*mcp.CallToolResult, SearchOutput, error) {
	query := strings.TrimSpace(in.Query)
	if query == "" {
		return nil, SearchOutput{}, errRequiredField("query")
	}

	limit := normalizeLimit(in.Limit, t.search)
	threshold := normalizeThreshold(in.Threshold, t.search.DefaultThreshold)

	project, err := resolveProject(ctx, t.store, t.sessions, req, in.Project, false)
	if err != nil {
		return nil, SearchOutput{}, err
	}

	var projectID *int64
	if project != nil {
		projectID = &project.NumericID
		_ = t.store.TouchProject(ctx, project.NumericID)
	}

	results, err := semanticSearch(ctx, t.store, t.embeddings, t.search, query, limit, threshold, projectID, nil)
	if err != nil {
		return nil, SearchOutput{}, err
	}

	return nil, SearchOutput{Results: results}, nil
}
