package main

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"strings"
	"time"

	"github.com/anthropics/anthropic-sdk-go"
	"github.com/anthropics/anthropic-sdk-go/packages/param"
)

// ErrModelNotFound is returned when the configured Anthropic model is no longer available
// (deprecated or removed). Callers can use errors.Is to detect this and surface an
// actionable message to admins/owners while keeping the response vague for regular users.
var ErrModelNotFound = errors.New("model not found or deprecated")

func (b *Bot) getAnthropicResponse(ctx context.Context, messages []anthropic.BetaMessageParam, isNewChat, isOwner, isEmojiOnly bool, username string, firstName string, lastName string, isPremium bool, languageCode string, messageTime int) ([]string, error) {
	// Use prompts from config
	var systemMessage string
	if isNewChat {
		systemMessage = b.config.SystemPrompts["new_chat"]
	} else {
		systemMessage = b.config.SystemPrompts["continue_conversation"]
	}

	// Combine default prompt with custom instructions
	systemMessage = b.config.SystemPrompts["default"] + " " + b.config.SystemPrompts["custom_instructions"] + " " + systemMessage

	// Handle username placeholder
	usernameValue := username
	if username == "" {
		usernameValue = "unknown" // Use "unknown" when username is not available
	}
	systemMessage = strings.ReplaceAll(systemMessage, "{username}", usernameValue)

	// Handle firstname placeholder
	firstnameValue := firstName
	if firstName == "" {
		firstnameValue = "unknown" // Use "unknown" when first name is not available
	}
	systemMessage = strings.ReplaceAll(systemMessage, "{firstname}", firstnameValue)

	// Handle lastname placeholder
	lastnameValue := lastName
	if lastName == "" {
		lastnameValue = "" // Empty string when last name is not available
	}
	systemMessage = strings.ReplaceAll(systemMessage, "{lastname}", lastnameValue)

	// Handle language code placeholder
	langValue := languageCode
	if languageCode == "" {
		langValue = "en" // Default to English when language code is not available
	}
	systemMessage = strings.ReplaceAll(systemMessage, "{language}", langValue)

	// Handle premium status
	premiumStatus := "regular user"
	if isPremium {
		premiumStatus = "premium user"
	}
	systemMessage = strings.ReplaceAll(systemMessage, "{premium_status}", premiumStatus)

	// Handle time awareness
	timeObj := time.Unix(int64(messageTime), 0)
	hour := timeObj.Hour()
	var timeContext string
	if hour >= 5 && hour < 12 {
		timeContext = "morning"
	} else if hour >= 12 && hour < 18 {
		timeContext = "afternoon"
	} else if hour >= 18 && hour < 22 {
		timeContext = "evening"
	} else {
		timeContext = "night"
	}
	systemMessage = strings.ReplaceAll(systemMessage, "{time_context}", timeContext)

	if !isOwner {
		systemMessage += " " + b.config.SystemPrompts["avoid_sensitive"]
	}

	if isEmojiOnly {
		systemMessage += " " + b.config.SystemPrompts["respond_with_emojis"]
	}

	// Debug logging
	InfoLogger.Printf("Sending %d messages to Anthropic", len(messages))

	params := anthropic.BetaMessageNewParams{
		Model:     b.config.Model,
		MaxTokens: 1000,
		Messages:  messages,
		System:    []anthropic.BetaTextBlockParam{{Text: systemMessage}},
	}

	// Apply temperature if set in config
	if b.config.Temperature != nil {
		params.Temperature = param.NewOpt(float64(*b.config.Temperature))
	}

	// MCP servers + matching toolset entries. The mcp-client-2025-11-20 beta
	// requires per-tool filtering on the toolset (Configs + DefaultConfig),
	// NOT the deprecated per-server tool_configuration block.
	if len(b.config.MCPServers) > 0 {
		mcpServers := make([]anthropic.BetaRequestMCPServerURLDefinitionParam, 0, len(b.config.MCPServers))
		tools := make([]anthropic.BetaToolUnionParam, 0, len(b.config.MCPServers))
		for _, s := range b.config.MCPServers {
			srv := anthropic.BetaRequestMCPServerURLDefinitionParam{
				Name: s.Name,
				URL:  s.URL,
			}
			if s.AuthorizationToken != "" {
				srv.AuthorizationToken = param.NewOpt(s.AuthorizationToken)
			}
			mcpServers = append(mcpServers, srv)

			toolset := &anthropic.BetaMCPToolsetParam{
				MCPServerName: s.Name,
			}
			if len(s.AllowedTools) > 0 {
				toolset.DefaultConfig = anthropic.BetaMCPToolDefaultConfigParam{
					Enabled: param.NewOpt(false),
				}
				toolset.Configs = make(map[string]anthropic.BetaMCPToolConfigParam, len(s.AllowedTools))
				for _, tool := range s.AllowedTools {
					toolset.Configs[tool] = anthropic.BetaMCPToolConfigParam{
						Enabled: param.NewOpt(true),
					}
				}
			}
			tools = append(tools, anthropic.BetaToolUnionParam{OfMCPToolset: toolset})
		}
		params.MCPServers = mcpServers
		params.Tools = tools
		params.Betas = []anthropic.AnthropicBeta{anthropic.AnthropicBetaMCPClient2025_11_20}
	}

	resp, err := b.anthropicClient.Beta.Messages.New(ctx, params)
	if err != nil {
		var apiErr *anthropic.Error
		if errors.As(err, &apiErr) && apiErr.StatusCode == http.StatusNotFound {
			return nil, fmt.Errorf("%w: %s", ErrModelNotFound, b.config.Model)
		}
		return nil, fmt.Errorf("error creating Anthropic message: %w", err)
	}

	// Collect text blocks as separate segments so the Telegram delivery layer
	// can render each as its own message (matches the conversational rhythm
	// Claude uses around tool calls). Callers that want one joined string
	// (voice TTS, stickers) do strings.Join themselves.
	var segments []string
	for _, block := range resp.Content {
		switch block.Type {
		case "text":
			t := strings.TrimSpace(block.Text)
			if t != "" {
				segments = append(segments, t)
			}
		case "mcp_tool_use":
			InfoLogger.Printf("[mcp] tool_use server=%q name=%q id=%q input=%s",
				block.ServerName, block.Name, block.ID, string(block.Input))
		case "mcp_tool_result":
			preview := block.JSON.Content.Raw()
			if len(preview) > 500 {
				preview = preview[:500] + "...(truncated)"
			}
			InfoLogger.Printf("[mcp] tool_result tool_use_id=%q server=%q is_error=%v content=%s",
				block.ToolUseID, block.ServerName, block.IsError, preview)
		default:
			InfoLogger.Printf("[mcp] block type=%q (unhandled)", block.Type)
		}
	}
	if len(segments) == 0 {
		return nil, fmt.Errorf("unexpected response format from Anthropic")
	}
	return segments, nil
}
