package handler

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/gin-gonic/gin"

	"infogenie-backend/config"
	"infogenie-backend/internal/service"
)

type AIModelHandler struct{}

func NewAIModelHandler() *AIModelHandler { return &AIModelHandler{} }

// 输入长度限制
const (
	maxInputLen     = 5000
	maxChatMsgCount = 20
)

// 允许用户选择的模型白名单
var allowedModels = map[string]map[string]bool{
	"deepseek": {
		"deepseek-chat":     true,
		"deepseek-reasoner": true,
	},
	"kimi": {
		"kimi-k2-0905-preview": true,
		"kimi-k2-0711-preview": true,
	},
}

func safeAIError(err error) string {
	log.Printf("AI调用失败: %v", err)
	return "AI 服务暂时不可用，请稍后重试"
}

func validateTextLen(text string, label string) (string, error) {
	t := strings.TrimSpace(text)
	if t == "" {
		return "", fmt.Errorf("%s不能为空", label)
	}
	if len(t) > maxInputLen {
		return "", fmt.Errorf("%s超出长度限制（最大 %d 字符）", label, maxInputLen)
	}
	return t, nil
}

type aiModelChatInput struct {
	Messages []service.ChatMessage
	Provider string
	Model    string
}

// bindAIModelChat 绑定并校验统一 chat / chat/stream 请求体；失败时已写入 JSON 响应。
func bindAIModelChat(c *gin.Context) (aiModelChatInput, bool) {
	var req struct {
		Messages []service.ChatMessage `json:"messages"`
		Provider string                `json:"provider"`
		Model    string                `json:"model"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求数据为空"})
		return aiModelChatInput{}, false
	}
	if req.Provider == "" {
		req.Provider = "deepseek"
	}
	if req.Model == "" {
		req.Model = "deepseek-chat"
	}
	if models, ok := allowedModels[req.Provider]; !ok || !models[req.Model] {
		c.JSON(http.StatusBadRequest, gin.H{"error": "不支持的模型"})
		return aiModelChatInput{}, false
	}
	if len(req.Messages) == 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "消息内容不能为空"})
		return aiModelChatInput{}, false
	}
	if len(req.Messages) > maxChatMsgCount {
		c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("消息数量不能超过 %d 条", maxChatMsgCount)})
		return aiModelChatInput{}, false
	}
	for _, m := range req.Messages {
		if len(m.Content) > maxInputLen {
			c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("单条消息长度不能超过 %d 字符", maxInputLen)})
			return aiModelChatInput{}, false
		}
	}
	return aiModelChatInput{Messages: req.Messages, Provider: req.Provider, Model: req.Model}, true
}

// POST /api/aimodelapp/chat
func (h *AIModelHandler) Chat(c *gin.Context) {
	in, ok := bindAIModelChat(c)
	if !ok {
		return
	}
	content, err := service.CallAI(in.Provider, in.Model, in.Messages)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"success":   true,
		"content":   content,
		"provider":  in.Provider,
		"model":     in.Model,
		"timestamp": time.Now().Format(time.RFC3339),
	})
}

// POST /api/aimodelapp/chat/stream — SSE 透传上游 OpenAI 兼容流（data: {...}\\n\\n / [DONE]）
func (h *AIModelHandler) ChatStream(c *gin.Context) {
	in, ok := bindAIModelChat(c)
	if !ok {
		return
	}
	upstream, statusCode, err := service.OpenAIChatStream(c.Request.Context(), in.Provider, in.Model, in.Messages)
	if err != nil {
		if statusCode == 0 {
			c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
			return
		}
		c.JSON(http.StatusBadGateway, gin.H{"error": safeAIError(err)})
		return
	}
	defer upstream.Close()

	hdr := c.Writer.Header()
	hdr.Set("Content-Type", "text/event-stream; charset=utf-8")
	hdr.Set("Cache-Control", "no-cache")
	hdr.Set("Connection", "keep-alive")
	hdr.Set("X-Accel-Buffering", "no")
	c.Status(http.StatusOK)

	flusher, ok := c.Writer.(http.Flusher)
	if !ok {
		_, _ = io.Copy(c.Writer, upstream)
		return
	}
	buf := make([]byte, 8192)
	for {
		select {
		case <-c.Request.Context().Done():
			return
		default:
		}
		n, rerr := upstream.Read(buf)
		if n > 0 {
			if _, werr := c.Writer.Write(buf[:n]); werr != nil {
				return
			}
			flusher.Flush()
		}
		if rerr == io.EOF {
			return
		}
		if rerr != nil {
			return
		}
	}
}

// POST /api/aimodelapp/name-analysis
func (h *AIModelHandler) NameAnalysis(c *gin.Context) {
	var req struct {
		Name string `json:"name"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "姓名不能为空"})
		return
	}
	name, err := validateTextLen(req.Name, "姓名")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	prompt := fmt.Sprintf(`你是一位专业的姓名学专家和语言学家，请对输入的姓名进行全面分析。请直接输出分析结果，不要包含任何思考过程或<think>标签。

姓名：%s

请按照以下格式严格输出分析结果：

【稀有度评分】
评分：X%%
评价：[对稀有度的详细说明，包括姓氏和名字的常见程度分析]

【音韵评价】
评分：X%%
评价：[对音韵美感的分析，包括声调搭配、读音流畅度、音律和谐度等]

【含义解读】
[详细分析姓名的寓意内涵，包括：
1. 姓氏的历史渊源和文化背景
2. 名字各字的含义和象征
3. 整体姓名的寓意组合
4. 可能体现的父母期望或文化内涵
5. 与传统文化、诗词典故的关联等]

要求：
1. 评分必须是1-100的整数百分比，要有明显区分度，避免雷同
2. 分析要专业、客观、有依据，评分要根据实际情况有所差异
3. 含义解读要详细深入，至少150字
4. 严格按照上述格式输出，不要添加思考过程、<think>标签或其他内容
5. 如果是生僻字或罕见姓名，要特别说明
6. 直接输出最终结果，不要显示推理过程`, name)

	messages := []service.ChatMessage{{Role: "user", Content: prompt}}
	content, err := service.CallDeepSeek(messages, "", 3)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":   true,
		"analysis":  content,
		"name":      name,
		"timestamp": time.Now().Format(time.RFC3339),
	})
}

// POST /api/aimodelapp/variable-naming
func (h *AIModelHandler) VariableNaming(c *gin.Context) {
	var req struct {
		Description string `json:"description"`
		Language    string `json:"language"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "变量描述不能为空"})
		return
	}
	desc, err := validateTextLen(req.Description, "变量描述")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	lang := req.Language
	if lang == "" {
		lang = "javascript"
	}

	prompt := fmt.Sprintf(`你是一个专业的变量命名助手。请根据以下描述为变量生成合适的名称：

描述：%s

请为每种命名规范生成3个变量名建议：
1. camelCase (驼峰命名法)
2. PascalCase (帕斯卡命名法)
3. snake_case (下划线命名法)
4. kebab-case (短横线命名法)
5. CONSTANT_CASE (常量命名法)

请按JSON格式返回：
{"suggestions":{"camelCase":[{"name":"变量名","description":"说明"}],"PascalCase":[{"name":"变量名","description":"说明"}],"snake_case":[{"name":"变量名","description":"说明"}],"kebab-case":[{"name":"变量名","description":"说明"}],"CONSTANT_CASE":[{"name":"变量名","description":"说明"}]}}

只返回JSON格式的结果，不要包含其他文字。`, desc)

	messages := []service.ChatMessage{{Role: "user", Content: prompt}}
	content, err := service.CallDeepSeek(messages, "", 3)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":     true,
		"suggestions": extractOrRaw(content),
		"description": desc,
		"language":    lang,
		"timestamp":   time.Now().Format(time.RFC3339),
	})
}

// POST /api/aimodelapp/poetry
func (h *AIModelHandler) Poetry(c *gin.Context) {
	var req struct {
		Theme string `json:"theme"`
		Style string `json:"style"`
		Mood  string `json:"mood"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "诗歌主题不能为空"})
		return
	}
	theme, err := validateTextLen(req.Theme, "诗歌主题")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	style := req.Style
	if style == "" {
		style = "现代诗"
	}
	mood := req.Mood
	if mood == "" {
		mood = "自由发挥"
	}

	prompt := fmt.Sprintf(`你是一位才华横溢的诗人，请根据以下要求创作一首诗歌。

主题：%s
风格：%s
情感基调：%s

创作要求：
1. 紧扣主题，情感真挚
2. 语言优美，意境深远
3. 符合指定的诗歌风格
4. 长度适中，朗朗上口
5. 如果是古体诗，注意平仄和韵律

请直接输出诗歌作品，不需要额外的解释或分析。`, theme, style, mood)

	messages := []service.ChatMessage{{Role: "user", Content: prompt}}
	content, err := service.CallDeepSeek(messages, "", 3)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":   true,
		"poem":      content,
		"theme":     theme,
		"style":     style,
		"mood":      mood,
		"timestamp": time.Now().Format(time.RFC3339),
	})
}

// POST /api/aimodelapp/translation
func (h *AIModelHandler) Translation(c *gin.Context) {
	var req struct {
		SourceText     string `json:"source_text"`
		TargetLanguage string `json:"target_language"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "翻译内容不能为空"})
		return
	}
	text, err := validateTextLen(req.SourceText, "翻译内容")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	targetLang := req.TargetLanguage
	if targetLang == "" {
		targetLang = "zh-CN"
	}

	langMap := map[string]string{
		"zh-CN": "中文（简体）", "zh-TW": "中文（繁体）", "en": "英语",
		"ja": "日语", "ko": "韩语", "fr": "法语", "de": "德语",
		"es": "西班牙语", "it": "意大利语", "pt": "葡萄牙语",
		"ru": "俄语", "ar": "阿拉伯语", "hi": "印地语",
		"th": "泰语", "vi": "越南语",
	}
	langName := langMap[targetLang]
	if langName == "" {
		langName = targetLang
	}

	prompt := fmt.Sprintf(`你是一位专业的翻译专家，精通多种语言的翻译工作。请将以下文本翻译成%s。

原文：%s

翻译要求：
1. 【信】- 忠实原文，准确传达原意
2. 【达】- 译文通顺流畅，符合目标语言的表达习惯
3. 【雅】- 用词优美得体，风格与原文相符

请按以下JSON格式返回翻译结果：
{"detected_language":"检测到的源语言","target_language":"%s","translation":"翻译结果","alternative_translations":["备选翻译1","备选翻译2"],"explanation":"翻译说明","pronunciation":"发音指导"}

只返回JSON格式的结果，不要包含其他文字。`, langName, text, langName)

	messages := []service.ChatMessage{{Role: "user", Content: prompt}}
	content, err := service.CallDeepSeek(messages, "", 3)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":            true,
		"translation_result": content,
		"source_text":        text,
		"target_language":    targetLang,
		"timestamp":          time.Now().Format(time.RFC3339),
	})
}

// POST /api/aimodelapp/classical_conversion
func (h *AIModelHandler) ClassicalConversion(c *gin.Context) {
	var req struct {
		ModernText  string `json:"modern_text"`
		Style       string `json:"style"`
		ArticleType string `json:"article_type"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "现代文内容不能为空"})
		return
	}
	text, err := validateTextLen(req.ModernText, "现代文内容")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	style := req.Style
	if style == "" {
		style = "古雅"
	}
	artType := req.ArticleType
	if artType == "" {
		artType = "散文"
	}

	prompt := fmt.Sprintf(`你是一位精通古代文言文的文学大师，擅长将现代文转换为优美的文言文。请将以下现代文转换为文言文。

现代文：%s
风格：%s
文体：%s

请按以下JSON格式返回转换结果：
{"classical_text":"转换后的文言文","translation_notes":"转换说明","style_analysis":"风格分析","difficulty_level":"难度等级","key_phrases":[{"modern":"现代词汇","classical":"文言文词汇","explanation":"转换说明"}],"cultural_elements":"文化内涵说明"}

只返回JSON格式的结果，不要包含其他文字。`, text, style, artType)

	messages := []service.ChatMessage{{Role: "user", Content: prompt}}
	content, err := service.CallDeepSeek(messages, "", 3)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":           true,
		"conversion_result": content,
		"modern_text":       text,
		"style":             style,
		"article_type":      artType,
		"timestamp":         time.Now().Format(time.RFC3339),
	})
}

// POST /api/aimodelapp/expression-maker
func (h *AIModelHandler) ExpressionMaker(c *gin.Context) {
	var req struct {
		Text  string `json:"text"`
		Style string `json:"style"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "文字内容不能为空"})
		return
	}
	text, err := validateTextLen(req.Text, "文字内容")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	style := req.Style
	if style == "" {
		style = "mixed"
	}

	styleMap := map[string]string{
		"mixed": "混合使用Emoji表情和颜文字", "emoji": "仅使用Emoji表情符号",
		"kaomoji": "仅使用颜文字", "cute": "使用可爱风格的表情符号",
		"cool": "使用酷炫风格的表情符号",
	}
	styleDesc := styleMap[style]
	if styleDesc == "" {
		styleDesc = styleMap["mixed"]
	}

	prompt := fmt.Sprintf(`你是一个专业的表情符号专家。请根据以下文字内容生成相应的表情符号：

文字内容：%s
表情风格：%s

请按JSON格式返回：
{"expressions":{"emoji":[{"symbol":"😊","description":"场景说明","intensity":"中等","usage":"使用建议"}],"kaomoji":[{"symbol":"(^_^)","description":"场景说明","intensity":"轻微","usage":"使用建议"}],"combination":[{"symbol":"🎉✨","description":"场景说明","intensity":"强烈","usage":"使用建议"}]},"summary":{"emotion_analysis":"情感分析","recommended_usage":"推荐使用场景","style_notes":"风格特点"}}

只返回JSON格式的结果，不要包含其他文字。`, text, styleDesc)

	messages := []service.ChatMessage{{Role: "user", Content: prompt}}
	content, err := service.CallDeepSeek(messages, "", 3)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":     true,
		"expressions": extractOrRaw(content),
		"text":        text,
		"style":       style,
		"timestamp":   time.Now().Format(time.RFC3339),
	})
}

// POST /api/aimodelapp/linux-command
func (h *AIModelHandler) LinuxCommand(c *gin.Context) {
	var req struct {
		TaskDescription string `json:"task_description"`
		DifficultyLevel string `json:"difficulty_level"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "任务描述不能为空"})
		return
	}
	desc, err := validateTextLen(req.TaskDescription, "任务描述")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	level := req.DifficultyLevel
	if level == "" {
		level = "beginner"
	}

	prompt := fmt.Sprintf(`你是一位Linux系统专家，请根据用户的任务描述生成相应的Linux命令。

任务描述：%s
用户水平：%s

请按JSON格式返回：
{"commands":[{"command":"具体命令","description":"说明","safety_level":"safe","explanation":"解释","example_output":"示例输出","alternatives":["替代命令"]}],"safety_warnings":["安全提示"],"prerequisites":["前置条件"],"related_concepts":["相关概念"]}

只返回JSON格式的结果，不要包含其他文字。`, desc, level)

	messages := []service.ChatMessage{{Role: "user", Content: prompt}}
	content, err := service.CallDeepSeek(messages, "", 3)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":          true,
		"command_result":   content,
		"task_description": desc,
		"difficulty_level": level,
		"timestamp":        time.Now().Format(time.RFC3339),
	})
}

// POST /api/aimodelapp/markdown_formatting
func (h *AIModelHandler) MarkdownFormatting(c *gin.Context) {
	var req struct {
		ArticleText    string `json:"article_text"`
		EmojiStyle     string `json:"emoji_style"`
		MarkdownOption string `json:"markdown_option"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "文章内容不能为空"})
		return
	}
	text, err := validateTextLen(req.ArticleText, "文章内容")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	emojiStyle := req.EmojiStyle
	if emojiStyle == "" {
		emojiStyle = "balanced"
	}
	mdOption := req.MarkdownOption
	if mdOption == "" {
		mdOption = "standard"
	}

	prompt := fmt.Sprintf(`你是一位专业的文档排版助手。请将用户提供的全文按"标准Markdown格式"进行排版，并在不改变任何原文内容的前提下进行结构化呈现。严格遵守以下规则：

1) 保留所有原始内容，严禁改写、删减或添加新内容。
2) 使用合理的Markdown结构（标题、分节、段落、列表、引用、表格如有必要、代码块仅当原文包含）。
3) 智能添加适量Emoji以增强可读性（%s），在标题、关键句、列表项等处点缀；避免过度使用，保持专业。
4) 保持语言与语气不变，只优化排版和表现形式。
5) 输出"纯Markdown文本"，不要包含任何JSON、HTML、XML、解释文字、或代码块围栏标记。

如果原文本较长，可在开头自动生成简洁的"目录"以便阅读。

原文如下：
%s`, emojiStyle, text)

	messages := []service.ChatMessage{{Role: "user", Content: prompt}}
	content, err := service.CallDeepSeek(messages, "", 3)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":            true,
		"formatted_markdown": content,
		"source_text":        text,
		"emoji_style":        emojiStyle,
		"markdown_option":    mdOption,
		"timestamp":          time.Now().Format(time.RFC3339),
	})
}

// POST /api/aimodelapp/kinship-calculator
func (h *AIModelHandler) KinshipCalculator(c *gin.Context) {
	var req struct {
		RelationChain string   `json:"relation_chain"`
		Dialects      []string `json:"dialects"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "亲属关系链不能为空"})
		return
	}
	chain, err := validateTextLen(req.RelationChain, "亲属关系链")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	dialects := req.Dialects
	if len(dialects) == 0 {
		dialects = []string{"粤语", "闽南语", "上海话", "四川话", "东北话", "客家话"}
	}

	prompt := fmt.Sprintf(`你是一位中国亲属称呼专家。请解析下面的亲属关系链，给出最终的亲属称呼。

请遵循：
1) 以中国大陆通行的标准普通话称呼为准。
2) 同时给出若干方言的对应称呼：%s。
3) 如存在地区差异或性别歧义，请在notes中说明。
4) 不要展示推理过程；只输出JSON。

严格按以下JSON结构输出：
{"mandarin_title":"标准普通话称呼","dialect_titles":{"粤语":{"title":"称呼","romanization":"粤拼","notes":"说明"}},"notes":"总体说明"}

关系链：%s`, strings.Join(dialects, "、"), chain)

	messages := []service.ChatMessage{{Role: "user", Content: prompt}}
	content, err := service.CallDeepSeek(messages, "", 3)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": safeAIError(err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success":        true,
		"kinship_result": content,
		"relation_chain": chain,
		"timestamp":      time.Now().Format(time.RFC3339),
	})
}

// GET /api/aimodelapp/models — 仅返回允许的模型列表
func (h *AIModelHandler) GetModels(c *gin.Context) {
	models := make(map[string][]string)
	for provider, modelSet := range allowedModels {
		for m := range modelSet {
			models[provider] = append(models[provider], m)
		}
	}
	c.JSON(http.StatusOK, gin.H{
		"success":          true,
		"models":           models,
		"default_provider": "deepseek",
		"default_model":    "deepseek-chat",
	})
}

func extractOrRaw(content string) interface{} {
	return content
}

// Ping 用于健康检查（从 config 引用原始配置可选）
func Ping(c *gin.Context) {
	_ = config.Cfg
	c.JSON(http.StatusOK, gin.H{
		"status":    "running",
		"timestamp": time.Now().Format(time.RFC3339),
	})
}
