package googleRSS

import (
	"context"
	"encoding/json"
	"fmt"
	"log/slog"
	"slices"
	"strings"

	toolRegister "github.com/pardnchiu/agenvoy/internal/tools/register"
	toolTypes "github.com/pardnchiu/agenvoy/internal/tools/types"
)

var timeRanges = []string{
	"1h", "3h", "6h", "12h", "24h", "7d",
}

func Register() {
	toolRegister.Regist(toolRegister.Def{
		Name:        "fetch_google_rss",
		AlwaysAllow: true,
		Concurrent:  true,
		Description: "[system-default] Search Google News RSS and return article titles, summaries, and links.",
		Parameters: map[string]any{
			"type": "object",
			"properties": map[string]any{
				"keyword": map[string]any{
					"type":        "string",
					"description": "Search keywords (e.g. 'TSMC earnings').",
				},
				"time_range": map[string]any{
					"type":        "string",
					"description": "Lookback window.",
					"default":     "7d",
					"enum":        timeRanges,
				},
				"ceid": map[string]any{
					"type":        "string",
					"description": "Edition ID (e.g. 'TW:zh-Hant', 'US:en').",
					"default":     "TW:zh-Hant",
				},
			},
			"required": []string{
				"keyword",
			},
		},
		Handler: func(ctx context.Context, e *toolTypes.Executor, args json.RawMessage) (string, error) {
			var params struct {
				Keyword   string `json:"keyword"`
				TimeRange string `json:"time_range"`
				CEID      string `json:"ceid"`
				// avoid small agent like 4.1 be stupid to call with different parameter name
				Query string `json:"query"`
				Q     string `json:"q"`
			}
			if err := json.Unmarshal(args, &params); err != nil {
				return "", fmt.Errorf("json.Unmarshal: %w", err)
			}

			keyword := strings.TrimSpace(params.Keyword)
			if keyword == "" {
				keyword = strings.TrimSpace(params.Query)
			}
			if keyword == "" {
				keyword = strings.TrimSpace(params.Q)
			}
			if keyword == "" {
				return "", fmt.Errorf("keyword is required")
			}

			// avoid small agent like 4.1 be stupid to call with not support value
			timeRange := strings.TrimSpace(params.TimeRange)
			if timeRange != "" && !slices.Contains(timeRanges, timeRange) {
				slog.Warn("invalid time_range, fallback to '7d'",
					slog.String("session", e.SessionID))
				timeRange = "7d"
			}

			var geo, lang string
			ceid := strings.TrimSpace(params.CEID)
			parts := strings.SplitN(ceid, ":", 2)
			if params.CEID == "" || len(parts) != 2 {
				slog.Warn("invalid CEID, fallback to 'TW:zh-Hant'",
					slog.String("session", e.SessionID))
				params.CEID = "TW:zh-Hant"
				geo, lang = "TW", "zh-Hant"
			} else {
				geo, lang = parts[0], parts[1]
			}
			return handler(ctx, keyword, timeRange, ceid, geo, lang)
		},
	})
}
