package ai

import (
	"errors"
	"fmt"
	"fonchain-fiee/pkg/cache"
	"fonchain-fiee/pkg/common/qwen"
	"fonchain-fiee/pkg/model/login"
	modelQwen "fonchain-fiee/pkg/model/qwen"
	"fonchain-fiee/pkg/service"
	"fonchain-fiee/pkg/utils"
	"regexp"
	"strings"
	"time"
	"unicode"

	"github.com/gin-gonic/gin"
)

// ImageGenerateRequest 文生图请求参数
type ImageGenerateRequest struct {
	Prompt         string   `json:"prompt"`
	Size           string   `json:"size"`
	NegativePrompt string   `json:"negative_prompt"`
	Watermark      bool     `json:"watermark"`
	PromptExtend   bool     `json:"prompt_extend"`
	Images         []string `json:"images"`
}

// ImageGenerateResponse 文生图响应数据
type ImageGenerateResponse struct {
	RequestID string   `json:"request_id"`
	Images    []string `json:"images"`
	Usage     struct {
		Height     int `json:"height"`
		Width      int `json:"width"`
		ImageCount int `json:"image_count"`
	} `json:"usage"`
}

// AIImageGenerate AI文生图接口
func AIImageGenerate(ctx *gin.Context) {
	var req ImageGenerateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		service.Error(ctx, errors.New("参数错误: "))
		return
	}
	//检测之前是否有图片生成
	//loginUserInfo := login.GetUserInfoFromC(ctx)
	loginUserInfo := login.Info{
		ID:                 1,
		Status:             0,
		Name:               "",
		Sex:                "",
		Nationality:        "",
		DocumentType:       0,
		CertificatePicture: "",
		Validity:           "",
		PlaceOfResidence:   "",
		GroupPhoto:         "",
		Attachment:         "",
		SubNum:             "",
		NotPassRemarks:     "",
		Domain:             "",
		TelNum:             "",
		SubscriberNumber:   "",
	}
	if req.Prompt == "" {
		service.Error(ctx, errors.New("提示词不能为空"))
		return
	}
	if req.Size == "" {
		req.Size = "1024*1024"
	}
	var lockKey, taskID, oldVal string
	if len(req.Images) == 0 {
		lockKey = "generate:text_image:" + fmt.Sprint(loginUserInfo.ID)
	} else {
		lockKey = "generate:edit_image:" + fmt.Sprint(loginUserInfo.ID)
	}
	reply := cache.RedisClient.SetNX(lockKey, time.Now().Format("2006-01-02 15:04:05"), time.Minute*60)
	if !reply.Val() {
		oldVal = cache.RedisClient.Get(lockKey).String()
		if len(oldVal) > 20 && strings.Index(oldVal, "_") != -1 {
			taskID = oldVal[strings.LastIndex(oldVal, "_")+1:]
		}
	} else {
		defer cache.RedisClient.Del(lockKey)
	}
	var resultTask, result *modelQwen.QwenImageResponse
	var err error
	if taskID == "" {
		if len(req.Images) == 0 {
			resultTask, err = qwen.GenerateTextImage(req.Prompt, req.Size)
			if err != nil {
				service.Error(ctx, err)
				return
			}
			taskID = resultTask.Output.TaskID
			cache.RedisClient.Set(lockKey, time.Now().Format("2006-01-02 15:04:05")+"_"+taskID, time.Minute*5)
		} else {
			resultTask, err = qwen.GenerateEditImage(req.Prompt, req.Images, req.Size)
			if err != nil {
				service.Error(ctx, err)
				return
			}
			if resultTask.Code != "" {
				service.Error(ctx, errors.New("文生图失败: "+resultTask.Message))
				return
			}
			taskID = resultTask.Output.TaskID
			cache.RedisClient.Set(lockKey, time.Now().Format("2006-01-02 15:04:05")+"_"+taskID, time.Minute*5)
		}
	}
	result, err = qwen.ImgTaskResult(taskID)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	cache.RedisClient.Del(lockKey)
	service.Success(ctx, result)
}

func OneText(ctx *gin.Context) {
	var req ImageGenerateRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		service.Error(ctx, errors.New("参数错误: "))
		return
	}
	type ResultAll struct {
		Result []struct {
			Url          string `json:"url"`
			OrigPrompt   string `json:"orig_prompt"`
			ActualPrompt string `json:"actual_prompt"`
		} `json:"result"`
		Title   string `json:"title"`
		Content string `json:"content"`
		Prompt  string `json:"prompt"`
	}
	var resultAll ResultAll
	if req.Prompt == "" {
		service.Error(ctx, errors.New("提示词不能为空"))
		return
	}
	if len(req.Images) > 3 {
		service.Error(ctx, errors.New("最多只能上传3张图片"))
		return
	}
	loginUserInfo := login.GetUserInfoFromC(ctx)
	if req.Size == "" {
		req.Size = "1024*1024"
	}
	var lockKey, taskID, oldVal string
	if len(req.Images) == 0 {
		lockKey = "generate:text_image:" + fmt.Sprint(loginUserInfo.ID)
	} else {
		lockKey = "generate:edit_image:" + fmt.Sprint(loginUserInfo.ID)
	}
	reply := cache.RedisClient.SetNX(lockKey, time.Now().Format("2006-01-02 15:04:05"), time.Minute*60)
	if !reply.Val() {
		oldVal = cache.RedisClient.Get(lockKey).String()
		if len(oldVal) > 20 && strings.Index(oldVal, "_") != -1 {
			taskID = oldVal[strings.LastIndex(oldVal, "_")+1:]
		}
	} else {
		defer cache.RedisClient.Del(lockKey)
	}
	var resultTask, result *modelQwen.QwenImageResponse
	var err error
	if taskID == "" {
		// 先进行聊天获取上下文
		chatReq, err1 := ChatReqGet(req)
		if err1 != nil {
			service.Error(ctx, err1)
			return
		}
		chatResp, err2 := qwen.Chat(*chatReq)
		if err2 != nil {
			service.Error(ctx, err2)
			return
		}
		if len(chatResp.Choices) == 0 {
			service.Error(ctx, errors.New("聊天返回结果为空"))
			return
		}
		req.Prompt = chatResp.Choices[0].Message.Content
		resultAll.Prompt = req.Prompt
		if len(req.Images) == 0 {
			resultTask, err = qwen.GenerateTextImage(req.Prompt, req.Size)
			if err != nil {
				service.Error(ctx, err)
				return
			}
			taskID = resultTask.Output.TaskID
			cache.RedisClient.Set(lockKey, time.Now().Format("2006-01-02 15:04:05")+"_"+taskID, time.Minute*5)
		} else {
			resultTask, err = qwen.GenerateEditImage(req.Prompt, req.Images, req.Size)
			if err != nil {
				service.Error(ctx, err)
				return
			}
			if resultTask.Code != "" {
				service.Error(ctx, errors.New("文生图失败: "+resultTask.Message))
				return
			}
			taskID = resultTask.Output.TaskID
			cache.RedisClient.Set(lockKey, time.Now().Format("2006-01-02 15:04:05")+"_"+taskID, time.Minute*5)
		}
	}
	result, err = qwen.ImgTaskResult(taskID)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	cache.RedisClient.Del(lockKey)
	if len(result.Output.Results) == 0 {
		service.Error(ctx, errors.New("图片生成失败"))
		return
	}
	resultAll.Title, resultAll.Content = extractTitleAndContent(req.Prompt)
	resultAll.Title = utils.TruncateString(resultAll.Title, 100)
	resultAll.Content = utils.TruncateString(resultAll.Content, 200)
	for _, v := range result.Output.Results {
		resultAll.Result = append(resultAll.Result, struct {
			Url          string `json:"url"`
			OrigPrompt   string `json:"orig_prompt"`
			ActualPrompt string `json:"actual_prompt"`
		}{
			Url:          v.URL,
			OrigPrompt:   v.OrigPrompt,
			ActualPrompt: v.ActualPrompt,
		})
	}
	service.Success(ctx, resultAll)
}

func MoreText(ctx *gin.Context) {
	var req modelQwen.MoreTextReq
	if err := ctx.ShouldBindJSON(&req); err != nil {
		service.Error(ctx, errors.New("参数错误 "))
		return
	}

	type ResultAll struct {
		Title   string `json:"title"`
		Content string `json:"content"`
		Result  []struct {
			Url          string `json:"url"`
			OrigPrompt   string `json:"orig_prompt"`
			ActualPrompt string `json:"actual_prompt"`
		} `json:"result"`
	}

	var resultAll ResultAll

	// 三个协程：两个去请求聊天，一个去生成图片
	type chatResult struct {
		title   string
		content string
		err     error
	}

	type imageResult struct {
		result *modelQwen.QwenImageResponse
		err    error
	}

	// 协程1：生成标题（标题和内容加附件图片都请求聊天生成文字）
	titleChan := make(chan chatResult, 1)
	go func() {
		chatReq, err := buildChatRequest(req.TitlePrompt, req.Images)
		if err != nil {
			titleChan <- chatResult{err: err}
			return
		}
		chatResp, err := qwen.Chat(*chatReq)
		if err != nil {
			titleChan <- chatResult{err: err}
			return
		}
		if len(chatResp.Choices) == 0 {
			titleChan <- chatResult{err: errors.New("标题聊天返回结果为空")}
			return
		}
		titleChan <- chatResult{title: chatResp.Choices[0].Message.Content}
	}()

	// 协程2：生成内容（标题和内容加附件图片都请求聊天生成文字）
	contentChan := make(chan chatResult, 1)
	go func() {
		chatReq, err := buildChatRequest(req.ContentPrompt, req.Images)
		if err != nil {
			contentChan <- chatResult{err: err}
			return
		}
		chatResp, err := qwen.Chat(*chatReq)
		if err != nil {
			contentChan <- chatResult{err: err}
			return
		}
		if len(chatResp.Choices) == 0 {
			contentChan <- chatResult{err: errors.New("内容聊天返回结果为空")}
			return
		}
		contentChan <- chatResult{content: chatResp.Choices[0].Message.Content}
	}()

	// 协程3：生成图片（图片要求加附件去生成图片）
	imageChan := make(chan imageResult, 1)
	go func() {
		// 先请求聊天获取图片提示词（图片要求加附件去生成图片）
		chatReq, err := buildChatRequest(req.ImagePrompt, req.Images)
		if err != nil {
			imageChan <- imageResult{err: err}
			return
		}
		fmt.Println("chat" + time.Now().Format("2006-01-02 15:04:05"))
		chatResp, err := qwen.Chat(*chatReq)
		if err != nil {
			imageChan <- imageResult{err: err}
			return
		}
		if len(chatResp.Choices) == 0 {
			imageChan <- imageResult{err: errors.New("图片提示词聊天返回结果为空")}
			return
		}
		imagePrompt := chatResp.Choices[0].Message.Content
		fmt.Println("chat ok" + time.Now().Format("2006-01-02 15:04:05"))
		// 生成图片（图片要求加附件去生成图片）
		size := "1024*1024"
		var resultTask *modelQwen.QwenImageResponse
		if len(req.Images) == 0 {
			resultTask, err = qwen.GenerateTextImage(imagePrompt, size)
		} else {
			resultTask, err = qwen.GenerateEditImage(imagePrompt, req.Images, size)
		}
		if err != nil {
			imageChan <- imageResult{err: err}
			return
		}
		if resultTask.Code != "" {
			imageChan <- imageResult{err: errors.New("文生图失败: " + resultTask.Message)}
			return
		}
		fmt.Println("task" + time.Now().Format("2006-01-02 15:04:05"))
		// 等待图片生成完成
		result, err := qwen.ImgTaskResult(resultTask.Output.TaskID)
		if err != nil {
			imageChan <- imageResult{err: err}
			return
		}
		fmt.Println("image" + time.Now().Format("2006-01-02 15:04:05"))
		imageChan <- imageResult{result: result}
	}()

	// 等待所有协程完成（并发收集结果）
	var titleRes chatResult
	var contentRes chatResult
	var imageRes imageResult

	// 使用 select 来并发等待所有结果
	completed := 0
	total := 3

	for completed < total {
		select {
		case titleRes = <-titleChan:
			completed++
		case contentRes = <-contentChan:
			completed++
		case imageRes = <-imageChan:
			completed++
		}
	}

	// 处理标题结果
	if titleRes.err != nil {
		service.Error(ctx, fmt.Errorf("生成标题失败: %v", titleRes.err))
		return
	}
	resultAll.Title = titleRes.title

	// 处理内容结果
	if contentRes.err != nil {
		service.Error(ctx, fmt.Errorf("生成内容失败: %v", contentRes.err))
		return
	}
	resultAll.Content = contentRes.content

	resultAll.Title = utils.TruncateString(resultAll.Title, 100)
	resultAll.Content = utils.TruncateString(resultAll.Content, 200)
	// 处理图片结果
	if imageRes.err != nil {
		service.Error(ctx, fmt.Errorf("生成图片失败: %v", imageRes.err))
		return
	}

	if imageRes.result == nil || len(imageRes.result.Output.Results) == 0 {
		service.Error(ctx, errors.New("图片生成失败"))
		return
	}

	// 组装图片结果
	for _, v := range imageRes.result.Output.Results {
		resultAll.Result = append(resultAll.Result, struct {
			Url          string `json:"url"`
			OrigPrompt   string `json:"orig_prompt"`
			ActualPrompt string `json:"actual_prompt"`
		}{
			Url:          v.URL,
			OrigPrompt:   v.OrigPrompt,
			ActualPrompt: v.ActualPrompt,
		})
	}
	service.Success(ctx, resultAll)
}

// buildChatRequest 组装聊天的参数（用于 MoreText）
func buildChatRequest(prompt string, images []string) (*modelQwen.ChatRequest, error) {
	if prompt == "" {
		return nil, errors.New("提示词不能为空")
	}
	var chatReq modelQwen.ChatRequest
	chatReq.Model = "qwen3-max" //qwen3-max qwen-plus qwen-flash
	var content []modelQwen.Content
	content = append(content, modelQwen.Content{Type: "text", Text: prompt})
	for _, v := range images {
		if v != "" {
			content = append(content, modelQwen.Content{Type: "image_url", ImageURL: &modelQwen.ImageURL{URL: v}})
		}
	}
	chatReq.Messages = []modelQwen.Message{
		{
			Role:    "user",
			Content: content,
		},
	}
	chatReq.Seed = time.Now().Unix()
	return &chatReq, nil
}

// ChatReqGet 组装聊天的参数
func ChatReqGet(req ImageGenerateRequest) (*modelQwen.ChatRequest, error) {
	return buildChatRequest(req.Prompt, req.Images)
}

func cleanTitle(s string) string {
	var b strings.Builder
	for _, r := range strings.TrimSpace(s) {
		if unicode.Is(unicode.Han, r) || unicode.IsLetter(r) || unicode.IsDigit(r) ||
			unicode.IsPunct(r) || unicode.IsSpace(r) {
			b.WriteRune(r)
		}
	}
	out := strings.ReplaceAll(b.String(), "*", "")
	out = strings.TrimSpace(out)
	return out
}

// extractTitleAndContent 从完整文本中提取 title 和 content
func extractTitleAndContent(text string) (title, content string) {
	reTitleLine := regexp.MustCompile(`(?m).*标题[:：]\s*(.+)$`)
	if m := reTitleLine.FindStringSubmatch(text); len(m) >= 2 {
		title = cleanTitle(m[1])
	}

	reContent := regexp.MustCompile(`(?s)标题[:：].*?\n\s*\n(.*?)(?:\n\s*\n📸|\n\s*\n#|$)`)
	if m := reContent.FindStringSubmatch(text); len(m) >= 2 {
		content = strings.TrimSpace(m[1])
		content = regexp.MustCompile(`\n+`).ReplaceAllString(content, "\n")
		// 如果你希望把段内换行变成句内空格，可用下面这一行代替上面换行替换
		// content = regexp.MustCompile(`\s*\n\s*`).ReplaceAllString(content, " ")
	}

	if content == "" && title != "" {
		idx := strings.Index(text, title)
		if idx >= 0 {
			after := text[idx+len(title):]
			after = strings.ReplaceAll(after, "**", "")
			// 截到 "📸" 或 第一个 "#" 标签
			if i := strings.Index(after, "📸"); i >= 0 {
				after = after[:i]
			} else if i := strings.Index(after, "#"); i >= 0 {
				after = after[:i]
			}
			content = strings.TrimSpace(after)
		}
	}

	return title, content
}
