package types

import "encoding/json"

// AnthropicBlock is a single content block in Anthropic Messages API. It can
// be text, image, document, tool_use, or tool_result. We decode the raw JSON
// once and keep the rest as RawData so downstream code (prompt building) can
// render every type faithfully.
type AnthropicBlock struct {
	Type string `json:"type"`

	// type=text
	Text string `json:"text,omitempty"`

	// type=tool_use
	ID    string          `json:"id,omitempty"`
	Name  string          `json:"name,omitempty"`
	Input json.RawMessage `json:"input,omitempty"`

	// type=tool_result
	ToolUseID string          `json:"tool_use_id,omitempty"`
	Content   json.RawMessage `json:"content,omitempty"`
	IsError   bool            `json:"is_error,omitempty"`

	// type=image / document
	Source json.RawMessage `json:"source,omitempty"`
	Title  string          `json:"title,omitempty"`
}

// AnthropicTextBlock kept for response serialisation (proxy always returns
// text blocks back to the client; it does not emit tool_use natively).
type AnthropicTextBlock struct {
	Type string `json:"type"`
	Text string `json:"text,omitempty"`
}

// AnthropicContent is a flexible field: it can be a plain string OR an array
// of blocks. Claude Code always sends the array form.
type AnthropicContent []AnthropicBlock

func (c *AnthropicContent) UnmarshalJSON(data []byte) error {
	var text string
	if err := json.Unmarshal(data, &text); err == nil {
		*c = []AnthropicBlock{{Type: "text", Text: text}}
		return nil
	}

	var blocks []AnthropicBlock
	if err := json.Unmarshal(data, &blocks); err != nil {
		return err
	}
	*c = blocks
	return nil
}

type AnthropicSystem AnthropicContent

func (s *AnthropicSystem) UnmarshalJSON(data []byte) error {
	return (*AnthropicContent)(s).UnmarshalJSON(data)
}

type AnthropicMessage struct {
	Role    string           `json:"role"`
	Content AnthropicContent `json:"content"`
}

// AnthropicTool mirrors Anthropic's `tools` entry shape. InputSchema is left
// as RawMessage so we can render it verbatim in a system prompt without
// caring about the exact JSON Schema structure.
type AnthropicTool struct {
	Name        string          `json:"name"`
	Description string          `json:"description,omitempty"`
	InputSchema json.RawMessage `json:"input_schema,omitempty"`
}

type AnthropicMessagesRequest struct {
	Model     string             `json:"model"`
	MaxTokens int                `json:"max_tokens"`
	Messages  []AnthropicMessage `json:"messages"`
	System    AnthropicSystem    `json:"system,omitempty"`
	Stream    bool               `json:"stream"`
	Tools     []AnthropicTool    `json:"tools,omitempty"`
}

type AnthropicMessagesResponse struct {
	ID         string               `json:"id"`
	Type       string               `json:"type"`
	Role       string               `json:"role"`
	Content    []AnthropicTextBlock `json:"content"`
	Model      string               `json:"model"`
	StopReason string               `json:"stop_reason"`
	Usage      AnthropicUsage       `json:"usage"`
}

type AnthropicUsage struct {
	InputTokens  int `json:"input_tokens"`
	OutputTokens int `json:"output_tokens"`
}
