package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

// 用于第一个 API 请求的结构体
type HeadPortraitPromptRequest struct {
	Name string `json:"name"`
}

// 用于接收第一个 API 响应的结构体
type PromptResponse struct {
	Prompt string `json:"prompt"`
}

// 第二个 API 请求的结构体
type PortraitRequest struct {
	Prompt   string `json:"prompt"`
	Negative string `json:"negative"`
}

// 处理生成头像的 HTTP 请求
func GenerateAvatarHandler(c *gin.Context) {
	name := c.PostForm("name")
	if name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "未提供名字"})
		return
	}

	savePath := "./static/Worlds/headPortrait/"
	imagePath := savePath + name + ".png"

	// 检查本地是否已有头像图片
	if _, err := os.Stat(imagePath); err == nil {
		log.Println("已存在头像,直接返回")
		c.JSON(http.StatusOK, gin.H{"image_url": imagePath})
		return
	}

	// 打印进度条开始
	printProgressBar(0, "开始生成头像...")

	portraitData, err := GenerateHeadPortrait(name)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 更新进度条
	printProgressBar(70, "头像生成完毕,保存中...")

	// 保存头像图片到服务器
	imagePath, err = SaveImage(savePath, name+".png", portraitData)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 更新并完成进度条
	printProgressBar(100, "头像保存成功!")

	// 将图片地址直接作为响应返回
	c.JSON(http.StatusOK, gin.H{"image_url": imagePath})
}

// 生成人物头像,返回图片数据和错误信息
func GenerateHeadPortrait(name string) ([]byte, error) {
	promptAPI := "http://58.34.54.45:16666/generate_character_prompt"
	headPortraitAPI := "http://58.34.54.45:19666/"

	promptReq := HeadPortraitPromptRequest{Name: name}
	reqBody, err := json.Marshal(promptReq)
	if err != nil {
		return nil, fmt.Errorf("请求体编码失败: %v", err)
	}

	resp, err := http.Post(promptAPI, "application/json", bytes.NewBuffer(reqBody))
	if err != nil {
		return nil, fmt.Errorf("调用第一个 API 失败: %v", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应体失败: %v", err)
	}

	var promptResp PromptResponse
	if err := json.Unmarshal(body, &promptResp); err != nil {
		return nil, fmt.Errorf("响应解码失败: %v", err)
	}

	portraitReq := PortraitRequest{
		Prompt:   promptResp.Prompt,
		Negative: "normal",
	}
	reqBody, err = json.Marshal(portraitReq)
	if err != nil {
		return nil, fmt.Errorf("请求体编码失败: %v", err)
	}

	resp, err = http.Post(headPortraitAPI, "application/json", bytes.NewBuffer(reqBody))
	if err != nil {
		return nil, fmt.Errorf("调用第二个 API 失败: %v", err)
	}
	defer resp.Body.Close()

	portraitData, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取第二响应体失败: %v", err)
	}

	return portraitData, nil
}

// 保存图片到指定路径
func SaveImage(directory, filename string, data []byte) (string, error) {
	if err := os.MkdirAll(directory, 0755); err != nil {
		return "", fmt.Errorf("创建目录失败: %v", err)
	}

	filePath := directory + filename
	file, err := os.Create(filePath)
	if err != nil {
		return "", fmt.Errorf("创建文件失败: %v", err)
	}
	defer file.Close()

	if _, err = file.Write(data); err != nil {
		return "", fmt.Errorf("写入文件失败: %v", err)
	}

	return filePath, nil
}

// 打印绿色方块进度条
func printProgressBar(percentage int, message string) {
	barLength := 50 // 进度条长度
	progress := int(float64(percentage) / 100.0 * float64(barLength))

	// 使用绿色方块表示进度
	bar := strings.Repeat("\033[32m█\033[0m", progress) + strings.Repeat(" ", barLength-progress)

	// 使用 \r 将光标移动到行首,确保进度条在同一行上更新
	fmt.Printf("\r[%s] %d%% - %s", bar, percentage, message)
	if percentage == 100 {
		fmt.Println() // 进度条完成,换行
	}
}

func main() {
	router := gin.Default()
	router.POST("/generate_avatar", GenerateAvatarHandler)
	router.Run(":8080")
}