package models

import "encoding/json"

// Responses API request types

// ResponsesRequest maps to POST /v1/responses body (OpenAI Responses API format).
// The `input` field can be a string or an array of message objects.
type ResponsesRequest struct {
	Model           string          `json:"model"`
	Input           json.RawMessage `json:"input"` // string or []ResponseInputMessage
	Instructions    string          `json:"instructions,omitempty"`
	Temperature     *float64        `json:"temperature,omitempty"`
	MaxOutputTokens *uint32         `json:"max_output_tokens,omitempty"`
	TopP            *float64        `json:"top_p,omitempty"`
	Stream          *bool           `json:"stream,omitempty"`
	Tools           json.RawMessage `json:"tools,omitempty"`
	ToolChoice      json.RawMessage `json:"tool_choice,omitempty"`
	Store           *bool           `json:"store,omitempty"`
}

// ResponseInputMessage represents a single message in the input array.
type ResponseInputMessage struct {
	Role    string          `json:"role"`
	Content json.RawMessage `json:"content"` // string or []ContentPart
}

// Responses API response types

// ResponsesResponse maps to OpenAI /v1/responses response.
type ResponsesResponse struct {
	ID      string                `json:"id"`
	Object  string                `json:"object"`
	Model   string                `json:"model"`
	Output  []ResponsesOutputItem `json:"output"`
	Usage   *ResponsesUsage       `json:"usage,omitempty"`
}

// ResponsesOutputItem represents an item in the output array.
// For messages: type="message", role, content[].
// For function calls: type="function_call", id, name, arguments, status.
type ResponsesOutputItem struct {
	Type      string                   `json:"type"`
	Role      string                   `json:"role,omitempty"`
	Content   []ResponsesOutputContent `json:"content,omitempty"`
	ID        string                   `json:"id,omitempty"`
	Name      string                   `json:"name,omitempty"`
	Arguments string                   `json:"arguments,omitempty"`
	Status    string                   `json:"status,omitempty"`
}

// ResponsesOutputContent represents content parts within an output message.
type ResponsesOutputContent struct {
	Type        string                   `json:"type"`
	Text        string                   `json:"text,omitempty"`
	Annotations []json.RawMessage        `json:"annotations,omitempty"`
}

// ResponsesUsage maps to the usage block in Responses API.
type ResponsesUsage struct {
	InputTokens          uint32                    `json:"input_tokens"`
	OutputTokens         uint32                    `json:"output_tokens"`
	TotalTokens          uint32                    `json:"total_tokens"`
	InputTokensDetails   *ResponsesInputTokensDetails  `json:"input_tokens_details,omitempty"`
	OutputTokensDetails  *ResponsesOutputTokensDetails `json:"output_tokens_details,omitempty"`
}

// ResponsesInputTokensDetails maps input token details.
type ResponsesInputTokensDetails struct {
	CachedTokens uint32 `json:"cached_tokens"`
}

// ResponsesOutputTokensDetails maps output token details.
type ResponsesOutputTokensDetails struct {
	ReasoningTokens uint32 `json:"reasoning_tokens"`
}

// ToUsage converts ResponsesUsage to the unified Usage model.
func (u *ResponsesUsage) ToUsage() *Usage {
	usage := &Usage{
		PromptTokens:     u.InputTokens,
		CompletionTokens: u.OutputTokens,
		TotalTokens:      u.TotalTokens,
	}
	if u.InputTokensDetails != nil && u.InputTokensDetails.CachedTokens > 0 {
		usage.CacheReadTokens = &u.InputTokensDetails.CachedTokens
	}
	if u.OutputTokensDetails != nil && u.OutputTokensDetails.ReasoningTokens > 0 {
		usage.ReasoningTokens = &u.OutputTokensDetails.ReasoningTokens
	}
	return usage
}

// ResponsesStreamChunk represents an SSE chunk from the Responses streaming endpoint.
type ResponsesStreamChunk struct {
	Type   string          `json:"type"`
	Response *ResponsesStreamPayload `json:"response,omitempty"`
	Item   *ResponsesStreamPayloadItem `json:"item,omitempty"`
	Delta  *ResponsesStreamDelta `json:"delta,omitempty"`
}

// ResponsesStreamPayload represents the "response" field in some SSE chunks.
type ResponsesStreamPayload struct {
	Object    string          `json:"object"`
	ID        string          `json:"id"`
	Model     string          `json:"model"`
	Usage     *ResponsesUsage  `json:"usage,omitempty"`
}

// ResponsesStreamPayloadItem represents the "item" field in SSE chunks.
type ResponsesStreamPayloadItem struct {
	Type    string                   `json:"type"`
	Role    string                   `json:"role,omitempty"`
	Content []ResponsesOutputContent `json:"content,omitempty"`
	ID      string                   `json:"id,omitempty"`
	Name    string                   `json:"name,omitempty"`
	Status  string                   `json:"status,omitempty"`
}

// ResponsesStreamDelta represents a content delta in streaming.
type ResponsesStreamDelta struct {
	ContentIndex int    `json:"content_index"`
	Type        string `json:"type"`
	Text        string `json:"text,omitempty"`
}

// UnifiedResponsesRequest is the internal unified format for Responses API.
type UnifiedResponsesRequest struct {
	ClientID         string
	Model            string
	Input            string            // normalized input text
	InputMessages    []ResponseInputMessage // structured input messages (if provided as array)
	Instructions     string
	Temperature      *float64
	MaxOutputTokens  *uint32
	TopP             *float64
	Stream           bool
	Tools            json.RawMessage
	ToolChoice       json.RawMessage
	Store            bool
}
