package pkulaw

import (
	"encoding/json"
	"strings"
)

func mapToolArguments(
	action string,
	topology string,
	raw json.RawMessage,
) (map[string]any, error) {
	switch action {
	case ActionSearchLawArticles:
		var input struct {
			Query string `json:"query"`
		}
		if err := json.Unmarshal(raw, &input); err != nil {
			return nil, invalidInput()
		}
		query := strings.TrimSpace(input.Query)
		if query == "" {
			return nil, invalidInput()
		}
		switch topology {
		case TopologyAggregate:
			return map[string]any{"query": query}, nil
		case TopologyFallback:
			return map[string]any{"text": query}, nil
		default:
			return nil, invalidConnectionTopology()
		}
	case ActionGetLawArticle:
		var input struct {
			Title  string `json:"title"`
			Number string `json:"number"`
		}
		if err := json.Unmarshal(raw, &input); err != nil {
			return nil, invalidInput()
		}
		title := strings.TrimSpace(input.Title)
		number := strings.TrimSpace(input.Number)
		if title == "" || number == "" {
			return nil, invalidInput()
		}
		return map[string]any{
			"title":  title,
			"number": number,
		}, nil
	case ActionSearchLaws:
		fields, err := mapSearchFields(raw)
		if err != nil {
			return nil, err
		}
		switch topology {
		case TopologyAggregate:
			return fields, nil
		case TopologyFallback:
			return map[string]any{
				"lawInput": mapFallbackSearchFields(fields),
			}, nil
		default:
			return nil, invalidConnectionTopology()
		}
	case ActionSearchCases:
		var input struct {
			Text string `json:"text"`
		}
		if err := json.Unmarshal(raw, &input); err != nil {
			return nil, invalidInput()
		}
		text := strings.TrimSpace(input.Text)
		if text == "" {
			return nil, invalidInput()
		}
		return map[string]any{"text": text}, nil
	case ActionSearchCaseDocuments:
		fields, err := mapSearchFields(raw)
		if err != nil {
			return nil, err
		}
		switch topology {
		case TopologyAggregate:
			return fields, nil
		case TopologyFallback:
			return map[string]any{
				"caseInput": mapFallbackSearchFields(fields),
			}, nil
		default:
			return nil, invalidConnectionTopology()
		}
	default:
		return nil, actionNotFound()
	}
}

func mapSearchFields(raw json.RawMessage) (map[string]any, error) {
	var input struct {
		Title    *string `json:"title"`
		Fulltext *string `json:"fulltext"`
	}
	if err := json.Unmarshal(raw, &input); err != nil {
		return nil, invalidInput()
	}
	fields := make(map[string]any, 2)
	if input.Title != nil {
		title := strings.TrimSpace(*input.Title)
		if title == "" {
			return nil, invalidInput()
		}
		fields["title"] = title
	}
	if input.Fulltext != nil {
		fulltext := strings.TrimSpace(*input.Fulltext)
		if fulltext == "" {
			return nil, invalidInput()
		}
		fields["fulltext"] = fulltext
	}
	if len(fields) == 0 {
		return nil, invalidInput()
	}
	return fields, nil
}

func mapFallbackSearchFields(fields map[string]any) map[string]any {
	mapped := make(map[string]any, len(fields))
	if title, ok := fields["title"]; ok {
		mapped["Title"] = title
	}
	if fulltext, ok := fields["fulltext"]; ok {
		mapped["Fulltext"] = fulltext
	}
	return mapped
}
