package aiwire

import (
	"encoding/json"
	"strings"
)

// RespRequest 是 POST /responses 请求体(无状态子集;有状态字段仅用于拒绝判定)。
type RespRequest struct {
	Model              string          `json:"model"`
	Input              RespInput       `json:"input"`
	Instructions       string          `json:"instructions,omitempty"`
	MaxOutputTokens    *int            `json:"max_output_tokens,omitempty"`
	Temperature        *float64        `json:"temperature,omitempty"`
	TopP               *float64        `json:"top_p,omitempty"`
	Tools              []RespTool      `json:"tools,omitempty"`
	ToolChoice         json.RawMessage `json:"tool_choice,omitempty"`
	ParallelToolCalls  *bool           `json:"parallel_tool_calls,omitempty"`
	Text               *RespText       `json:"text,omitempty"`
	Reasoning          *RespReasoning  `json:"reasoning,omitempty"`
	Stream             bool            `json:"stream,omitempty"`
	Store              *bool           `json:"store,omitempty"`
	PreviousResponseID string          `json:"previous_response_id,omitempty"`
	Conversation       json.RawMessage `json:"conversation,omitempty"`
	Background         *bool           `json:"background,omitempty"`
}

// RespInput 兼容 string 与 item 数组两种形态。
type RespInput struct {
	Text    string
	Items   []RespItem
	IsArray bool
}

func (in *RespInput) UnmarshalJSON(b []byte) error {
	t := strings.TrimSpace(string(b))
	if strings.HasPrefix(t, "\"") {
		return json.Unmarshal(b, &in.Text)
	}
	in.IsArray = true
	return json.Unmarshal(b, &in.Items)
}

// RespItem 承载 input 数组的各形态:message / function_call / function_call_output。
type RespItem struct {
	Type      string          `json:"type,omitempty"` // 缺省视为 message
	Role      string          `json:"role,omitempty"`
	Content   RespContent     `json:"content,omitempty"`
	ID        string          `json:"id,omitempty"`
	CallID    string          `json:"call_id,omitempty"`
	Name      string          `json:"name,omitempty"`
	Arguments string          `json:"arguments,omitempty"`
	Output    json.RawMessage `json:"output,omitempty"` // string 或部件数组
	Status    string          `json:"status,omitempty"`
}

// OutputText 拍平 function_call_output 的 output(string 或部件数组)。
func (it RespItem) OutputText() string {
	if len(it.Output) == 0 {
		return ""
	}
	var s string
	if err := json.Unmarshal(it.Output, &s); err == nil {
		return s
	}
	var parts []RespPart
	if err := json.Unmarshal(it.Output, &parts); err != nil {
		return string(it.Output)
	}
	texts := make([]string, 0, len(parts))
	for _, p := range parts {
		texts = append(texts, p.Text)
	}
	return strings.Join(texts, "\n")
}

// RespContent 兼容 string 与 part 数组两种形态。
type RespContent struct {
	Text    string
	Parts   []RespPart
	IsArray bool
}

func (c *RespContent) UnmarshalJSON(b []byte) error {
	t := strings.TrimSpace(string(b))
	if strings.HasPrefix(t, "\"") {
		return json.Unmarshal(b, &c.Text)
	}
	c.IsArray = true
	return json.Unmarshal(b, &c.Parts)
}

// JoinText 拍平内容为纯文本(input_text / output_text / refusal)。
func (c RespContent) JoinText() string {
	if !c.IsArray {
		return c.Text
	}
	texts := make([]string, 0, len(c.Parts))
	for _, p := range c.Parts {
		if p.Text != "" {
			texts = append(texts, p.Text)
		}
	}
	return strings.Join(texts, "\n")
}

// HasUnsupported 报告是否含网关无法承接的部件(文本 / input_image 之外,或依赖服务端文件存储)。
func (c RespContent) HasUnsupported() bool {
	for _, p := range c.Parts {
		switch p.Type {
		case "", "input_text", "output_text", "text", "refusal":
		case "input_image":
			if p.ImageURL == "" || p.FileID != "" {
				return true
			}
		default:
			return true
		}
	}
	return false
}

// RespPart 是 content 数组里的一个部件;input_image 的 image_url 为字符串(URL 或 data URI)。
type RespPart struct {
	Type     string `json:"type"`
	Text     string `json:"text,omitempty"`
	ImageURL string `json:"image_url,omitempty"`
	Detail   string `json:"detail,omitempty"`
	FileID   string `json:"file_id,omitempty"`
}

// RespTool 是 Responses 扁平工具定义(仅支持 type=function)。
type RespTool struct {
	Type        string          `json:"type"`
	Name        string          `json:"name,omitempty"`
	Description string          `json:"description,omitempty"`
	Parameters  json.RawMessage `json:"parameters,omitempty"`
	Strict      *bool           `json:"strict,omitempty"`
}

// RespText 收纳输出格式配置(text.format)。
type RespText struct {
	Format *RespTextFormat `json:"format,omitempty"`
}

// RespTextFormat 是扁平的 format 对象(text / json_object / json_schema)。
type RespTextFormat struct {
	Type   string          `json:"type"`
	Name   string          `json:"name,omitempty"`
	Schema json.RawMessage `json:"schema,omitempty"`
	Strict *bool           `json:"strict,omitempty"`
}

// RespReasoning 只透传 effort;summary 等忽略。
type RespReasoning struct {
	Effort string `json:"effort,omitempty"`
}

// RespUsage 是 Responses 口径的用量(input/output 命名)。
type RespUsage struct {
	InputTokens         int            `json:"input_tokens"`
	OutputTokens        int            `json:"output_tokens"`
	TotalTokens         int            `json:"total_tokens"`
	InputTokensDetails  RespInDetails  `json:"input_tokens_details"`
	OutputTokensDetails RespOutDetails `json:"output_tokens_details"`
}

// RespInDetails / RespOutDetails 恒零值输出(OCI 不提供细分)。
type RespInDetails struct {
	CachedTokens int `json:"cached_tokens"`
}

type RespOutDetails struct {
	ReasoningTokens int `json:"reasoning_tokens"`
}

// RespError 是 Response.error 字段。
type RespError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

// RespIncomplete 说明 status=incomplete 的原因。
type RespIncomplete struct {
	Reason string `json:"reason"`
}

// RespResponse 描述 /ai/v1/responses 非流式响应的常用顶层字段(文档用途)。
// 直通端点原样返回上游 JSON,未列字段(reasoning、incomplete_details 等)同样保留。
type RespResponse struct {
	ID        string          `json:"id"`
	Object    string          `json:"object"`
	CreatedAt int64           `json:"created_at"`
	Status    string          `json:"status"`
	Model     string          `json:"model"`
	Output    json.RawMessage `json:"output"`
	Usage     *RespUsage      `json:"usage,omitempty"`
	Error     *RespError      `json:"error,omitempty"`
}
