package modelprovider

import (
	"time"

	"github.com/openai/openai-go/v3"
	"github.com/openai/openai-go/v3/responses"
	"github.com/openai/openai-go/v3/shared"
)

type Role string

const (
	RoleUser      Role = "user"
	RoleAssistant Role = "assistant"
	RoleSystem    Role = "system"
)

const (
	PartText  PartType = "text"
	PartImage PartType = "image"
)

type Message struct {
	Role  Role   `json:"role"`
	Parts []Part `json:"parts,omitempty"` // 多模态分片（任选其一）
}

type PartType string

type Part struct {
	Type PartType `json:"type"`

	// 文本
	Text string `json:"text,omitempty"`

	// 图片（任选其一：URL/内联字节/已有文件ID）
	ImageURL   string `json:"image_url,omitempty"`
	ImageBytes []byte `json:"image_bytes,omitempty"`
	MIMEType   string `json:"mime_type,omitempty"` // "image/png" 等
}

type ChatRequest struct {
	Model        shared.ResponsesModel `json:"model"`
	Messages     []Message             `json:"messages"`
	Temperature  *float64              `json:"temperature,omitempty"`
	TopP         *float64              `json:"top_p,omitempty"`
	MaxTokens    *int                  `json:"max_tokens,omitempty"`
	VendorExtras map[string]any        `json:"vendor_extras,omitempty"`
	RequestID    string                `json:"request_id,omitempty"`
	IsStream     bool                  `json:"is_stream,omitempty"`
}

type Usage struct {
	PromptTokens     int `json:"prompt_tokens"`
	CompletionTokens int `json:"completion_tokens"`
	TotalTokens      int `json:"total_tokens"`
}

type AIError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

type Meta struct {
	CreatedAt time.Time         `json:"created_at"`
	Vendor    string            `json:"vendor"`
	ModelID   string            `json:"model_id,omitempty"`
	Extras    map[string]string `json:"extras,omitempty"`
}

type ChatResponse struct {
	ID      string   `json:"id"`
	Model   string   `json:"model"`
	Content string   `json:"content"`
	Usage   *Usage   `json:"usage,omitempty"`
	Err     *AIError `json:"err,omitempty"`
	Raw     any      `json:"raw,omitempty"`
	Meta    Meta     `json:"meta"`
}

// 模型信息（面向统一层）
type ModelInfo struct {
	// 逻辑 ID（仅在 RouterProvider 聚合时回填，如 "openai/gpt-4o-2024-08-06"）
	LogicalID string `json:"logical_id,omitempty"`

	// 供应商真实模型 ID（如 "gpt-4o-2024-08-06"）
	RealID string `json:"real_id"`

	// 供应商标识（如 "openai"）
	Vendor string `json:"vendor"`

	// 展示名（可选）
	DisplayName string `json:"display_name,omitempty"`

	// 能力信息（按需精简/扩展）
	ContextWindow    int      `json:"context_window,omitempty"` // 最大上下文
	SupportsStream   bool     `json:"supports_stream,omitempty"`
	InputModalities  []string `json:"input_modalities,omitempty"`  // e.g. ["text","image","audio"]
	OutputModalities []string `json:"output_modalities,omitempty"` // e.g. ["text","image"]

	// 定价/地区/版本等（可选）
	Region   string            `json:"region,omitempty"`
	Version  string            `json:"version,omitempty"`
	Metadata map[string]string `json:"metadata,omitempty"`

	// 供应商原始信息（调试/排障）
	Raw any `json:"raw,omitempty"`
}

// 便捷构造器（业务层直接用）
func NewPartText(s string) Part     { return Part{Type: PartText, Text: s} }
func NewPartImageURL(u string) Part { return Part{Type: PartImage, ImageURL: u} }
func NewPartImageBytes(b []byte, mt string) Part {
	return Part{Type: PartImage, ImageBytes: b, MIMEType: mt}
}

func MakeUserMsg(p []Part) Message {
	return Message{
		Role:  RoleUser,
		Parts: p,
	}
}

func MakeAssistantMsg(p []Part) Message {
	return Message{
		Role:  RoleAssistant,
		Parts: p,
	}
}

func MakeSystemMsg(p []Part) Message {
	return Message{
		Role:  RoleSystem,
		Parts: p,
	}
}

func PartsToOpenaiChatPartUnionParam(parts []Part) (result []openai.ChatCompletionContentPartUnionParam) {

	for _, p := range parts {
		switch p.Type {

		case PartText:
			if p.Text == "" {
				continue
			}
			result = append(result,
				openai.ChatCompletionContentPartUnionParam{
					OfText: &openai.ChatCompletionContentPartTextParam{
						Text: p.Text,
					},
				},
			)

		case PartImage:
			// 1️⃣ image_url 优先
			if p.ImageURL != "" {
				result = append(result,
					openai.ChatCompletionContentPartUnionParam{
						OfImageURL: &openai.ChatCompletionContentPartImageParam{
							ImageURL: openai.ChatCompletionContentPartImageImageURLParam{
								URL: p.ImageURL,
							},
						},
					},
				)
				continue
			}

			// 2️⃣ image_bytes（inline image）
			if len(p.ImageBytes) > 0 {
				result = append(result,
					openai.ChatCompletionContentPartUnionParam{
						OfImageURL: &openai.ChatCompletionContentPartImageParam{
							ImageURL: openai.ChatCompletionContentPartImageImageURLParam{
								URL: p.ImageURL,
							},
						},
					},
				)
			}
		}
	}
	return result
}

func PartsToOpenaiChatContentPartTextParam(parts []Part) (result []openai.ChatCompletionContentPartTextParam) {

	for _, p := range parts {
		if p.Type != PartText {
			continue
		}

		if p.Text == "" {
			continue
		}

		result = append(result,
			openai.ChatCompletionContentPartTextParam{
				Text: p.Text,
			},
		)
	}
	return result
}

func PartsToOpenaiChatAssistantMessageParamContentArrayOfContentPartUnion(
	parts []Part,
) (result []openai.ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) {

	for _, p := range parts {
		switch p.Type {
		case PartText:
			if p.Text == "" {
				continue
			}
			result = append(result,
				openai.ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion{
					OfText: &openai.ChatCompletionContentPartTextParam{
						Text: p.Text,
					},
				},
			)
		}
	}
	return result
}

func PartsToResponseInputItemUnionParam(role Role, parts []Part) (result responses.ResponseInputItemUnionParam) {
	var openaiRole responses.EasyInputMessageRole
	switch role {
	case RoleUser:
		openaiRole = responses.EasyInputMessageRoleUser
	case RoleAssistant:
		openaiRole = responses.EasyInputMessageRoleAssistant
	case RoleSystem:
		openaiRole = responses.EasyInputMessageRoleSystem
	}

	for _, p := range parts {
		switch p.Type {

		case PartText:
			if p.Text == "" {
				continue
			}

			result = responses.ResponseInputItemUnionParam{
				OfMessage: &responses.EasyInputMessageParam{Content: responses.EasyInputMessageContentUnionParam{OfString: openai.String(p.Text)},
					Role: openaiRole,
				}}
		}
	}
	return
}
