package controllers

import (
	"WorldEpcho/src/config"
	database "WorldEpcho/src/datasource"
	"WorldEpcho/src/models"
	"WorldEpcho/src/service"
	"WorldEpcho/src/utils"
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"strconv"
	"strings"
	"time"
)

//添加数字人
func AddDigitalPerson(ctx *gin.Context) {
	/*
	   判断用户是否登录
	*/
	userID, isLogin := service.IsUserLoggedIn(ctx)
	if !isLogin {
		log.Println("用户未登录")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户未登录"})
		return
	}
	/*
	  添加数字人
	*/
	//开启事务
	session := database.Engine.NewSession()
	defer session.Close() //延迟关闭session
	err := session.Begin()
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "开启事务失败!"})
		fmt.Println("开启事务失败")
		return
	}
	dpIQ := ctx.PostForm("IQ")
	var IQ int
	if dpIQ != "" {
		IQ, err = strconv.Atoi(dpIQ)
		if err != nil {
			fmt.Println("转换错误:", err)
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "IQ类型转换出错"})
			return
		}
	}

	var digitalPerson = models.DigitalPerson{
		Name:             ctx.PostForm("name"),
		Gender:           ctx.PostForm("gender"),
		Personality:      ctx.PostForm("personality"),
		Catchphrases:     ctx.PostForm("catchphrases"),
		BackgroundInfo:   ctx.PostForm("backgroundInfo"),
		Visibility:       ctx.PostForm("visibility"),
		Author:           userID,
		MindDeep:         IQ,
		InteractionCount: 0,
	}

	// 实现创建数字人
	err1 := models.CreateDigitalPerson(&digitalPerson, session)
	if err1 != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "创建数字人失败"})
		fmt.Println(config.ColorRed, err.Error(), config.ColorReset)
		// 如果数字人添加失败，回滚事务
		//		session.Rollback()
		return
	} else {
		/*
		   数字人添加成后,从数据库获取数字人Id,然后为数字人添加头像和封面
		*/
		digitalPersonInfo, err := models.GetDigitalPersonInfoTrans(&digitalPerson, session)
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "未查询到该数字人"})
			fmt.Println(config.ColorRed, "未查询到该数字人", config.ColorReset)
			// 如果查询数字人信息失败，回滚事务
			//			session.Rollback()
		}
		/*
			为数字人添加头像和封面
		*/
		digital_PersonId := digitalPersonInfo.Id
		digitalPersonId := utils.Strval(digital_PersonId)
		// 获取数字人的头像
		file, err := ctx.FormFile("avatar")
		if err != nil {
			fmt.Println("数字人头像从前端获取失败:", err)
			fmt.Println(config.ColorRed, err.Error(), config.ColorReset)
			return
		}

		// file保存到本地
		fileName := "./static/HuaSoul/" + "avatar" + digitalPersonId + ".png"

		err = ctx.SaveUploadedFile(file, fileName)
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "头像添加失败"})
			return
		}

		// 获取数字人的封面
		posterFile, err := ctx.FormFile("poster")
		if err != nil {
			utils.Failed(ctx, "获取数字人封面失败")
			return
		}
		// 保存数字人封面file，保存到本地
		posterFileName := "./static/HuaSoul/" + "poster" + digitalPersonId + ".png"
		err = ctx.SaveUploadedFile(posterFile, posterFileName)
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "数字人封面添加失败"})
			return
		}

		/*
		 创建SoulAsset资产实体
		*/
		//数字人资产上传操作
		//判断用户是否上传模型文件夹
		// 检查上传的文件是否存在,如果上传的文件不存在，有可能用户没有上传模型文件
		// 检查上传的文件
		form, _ := ctx.MultipartForm()
		files := form.File["mode_file"]
		fmt.Println("需要上传的模型文件: ", len(files))
		if len(files) != 0 {
			fmt.Println("需要上传的模型文件个数: ", len(files))
			//如果有文件上传，则保存模型文件
			FirstPath, err := UploadFolderHandler(ctx, digital_PersonId)
			if err != nil {
				ctx.JSON(http.StatusOK, gin.H{
					"code":    0,
					"message": "上传数字人模型文件失败!",
				})
				return
			}

			/*向数据库插入数字人模型文件*/
			mode_path := "/static/asset/" + digitalPersonId + "/" + FirstPath
			var soulAsset = models.SoulAsset{
				DigitalId:       digital_PersonId,
				ModelDriverType: ctx.PostForm("model_driver_type"),
				ModelPath:       mode_path,
				VoiceType:       ctx.PostForm("voice_type"),
			}
			err = models.CreateAsset(&soulAsset, session)
			if err != nil {
				ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "保存数字人资产至数据库失败"})
				// 如果创建数字人资产失败，回滚事务
				session.Rollback()
				return
			}

		} else {
			/*如果用户没有上传数字人模型文件夹*/
			mode_path := ""
			var soulAsset = models.SoulAsset{
				DigitalId:       digital_PersonId,
				ModelDriverType: ctx.PostForm("model_driver_type"),
				ModelPath:       mode_path,
				VoiceType:       ctx.PostForm("voice_type"),
			}
			err = models.CreateAsset(&soulAsset, session)
			if err != nil {
				ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "保存数字人资产至数据库失败"})
				// 如果创建数字人资产失败，回滚事务
				session.Rollback()
				return
			}
		}
		//提交事务
		err = session.Commit()
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "创建数字人失败! "})
			return
		}
		ctx.JSON(http.StatusOK, gin.H{"code": 1, "message": "创建数字人成功"})
	}

}

//根据数字人Id获取数字人信息
func QueryDigitalPersonByID(ctx *gin.Context) {
	/*
	   判断用户是否登录
	*/
	_, isLogin := service.IsUserLoggedIn(ctx)
	if !isLogin {
		log.Println("用户未登录")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户未登录"})
		return
	}
	//实现根据ID获取数字人的逻辑
	id := ctx.PostForm("id")
	var digitalId int64
	if id != "" {
		digital_id, err := strconv.ParseInt(id, 10, 64)
		if err != nil {
			fmt.Println("数字人id转换失败：", err)
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "数字人id类型不合法"})
			return
		}
		digitalId = digital_id
	} else {
		digitalId = 0
	}

	// 打印转换后的 digitalId 结果
	fmt.Println(digitalId)
	session := database.Engine.NewSession()
	defer session.Close() //延迟关闭session
	err := session.Begin()
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "开启事务失败!"})
		fmt.Println("开启事务失败")
		return
	}
	digitalPersonInfo, err := models.GetDigitalPersonAllInfoByID(digitalId, session)

	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "查询失败"})
		log.Println(err.Error())
		return
	}
	//fmt.Println(digitalPersonInfo)
	ctx.JSON(http.StatusOK, gin.H{"code": 1, "message": "查询成功", "digitalPerson": digitalPersonInfo})

}

//更新数字人信息操作
func EditDigitalPerson(ctx *gin.Context) {
	/*
	   判断用户是否登录
	*/
	userID, isLogin := service.IsUserLoggedIn(ctx)
	if !isLogin {
		//userID = 1
		log.Println("用户未登录")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户未登录"})
		return
	}
	// 实现更新数字人的逻辑
	digital_PersonId := ctx.PostForm("id")
	//digital_PersonId = "4"
	/**
	  转换数字人Id为int类型, 方便后面数字人信息从数据库中查询获取
	*/
	digital_id, err := strconv.Atoi(digital_PersonId)
	if err != nil {
		fmt.Println("数字人id转换失败:", err)
		log.Println(err.Error())
		return
	}
	dpIQ := ctx.PostForm("IQ")
	var IQ int
	if dpIQ != "" {

		IQ, err = strconv.Atoi(dpIQ)
		if err != nil {
			fmt.Println("转换错误:", err)
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "IQ类型转换出错"})
			return
		}
	}
	//开启事务
	session := database.Engine.NewSession()
	defer session.Close() //延迟关闭session
	err1 := session.Begin()
	if err1 != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "开启事务失败!"})
		fmt.Println("开启事务失败")
		return
	}
	/*
	  先根据前端传过来的数字人id获取数字人对象
	*/
	digitalPersonAllInfo, err := models.GetDigitalPersonAllInfoByID(int64(digital_id), session)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "查询失败"})
		log.Println(err.Error())
		return
	}
	fmt.Println(digitalPersonAllInfo)
	//ctx.JSON(http.StatusOK, gin.H{"code": 1, "message": "查询成功", "digitalPerson": digitalPersonAllInfo})

	//根据数字人id查询到创作者id
	authorId := digitalPersonAllInfo.DigitalPerson.Author
	//判断该用户是否拥有该数字人,并获取用户的权限等级值
	level, err := models.GetUserLevel(userID)
	if err != nil {
		log.Println("修改数字人时获取用户权限失败")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "更新时获取数字人信息时，获取用户权限失败!"})
		return
	}

	if !(userID == authorId || level == 0) {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "对不起,当前用户没有创建该数字人或者无权限修改该数字人"})
		return
	}
	/*
	   用户id为当前数字人的创作者id，或者用户的level为0的超级管理员可以进行数字人的修改
	*/
	//修改数字人信息
	var digitalPerson = models.DigitalPerson{
		Id:               int64(digital_id),
		Name:             ctx.PostForm("name"),
		Gender:           ctx.PostForm("gender"),
		Personality:      ctx.PostForm("personality"),
		Catchphrases:     ctx.PostForm("catchphrases"),
		BackgroundInfo:   ctx.PostForm("backgroundInfo"),
		Visibility:       ctx.PostForm("visibility"),
		Author:           authorId,
		InteractionCount: 0,
	}

	/*
	   更新数字人的头像和封面
	*/
	//1、获取数字人的头像
	file, err := ctx.FormFile("avatar")
	if err != nil {
		fmt.Println("数字人头像获取失败:", err)
		log.Println(err.Error())
		return
	}
	//2、file保存到本地
	fileName := "./static/HuaSoul/" + "avatar" + digital_PersonId + ".png"

	err = ctx.SaveUploadedFile(file, fileName)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "头像更新失败"})
		return
	}

	// 获取数字人的封面
	posterFile, err := ctx.FormFile("poster")
	if err != nil {
		utils.Failed(ctx, "获取数字人封面失败")
		return
	}

	posterFileName := "./static/HuaSoul/" + "poster" + digital_PersonId + ".png"
	err = ctx.SaveUploadedFile(posterFile, posterFileName)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "数字人封面更新失败"})
		return
	}
	ip := utils.ReadUserIP(ctx.Request)
	ip2 := utils.ReadUserIP2(ctx.Request)
	ip3 := utils.ReadUserIP3(ctx.Request)
	fmt.Println("|| =============================== 编辑数字人信息操作 ======================================== || ")
	log.Printf(config.ColorYellow+"时间为:%s , 用户主机IP:%s, 用户ID为: %d的用户, 修改了数字人: %s的信息。"+config.ColorReset, utils.GetNormalTimeString(time.Now()), ip, userID, digitalPerson.Name)
	digitalPerson.MindDeep = IQ
	fmt.Println("数字人思考深度: ", IQ)
	fmt.Println("|| ====================================================================================== || ")
	log.Printf(config.ColorYellow+"时间为:%s , 用户主机IP2 :%s"+config.ColorReset, utils.GetNormalTimeString(time.Now()), ip2)
	log.Printf(config.ColorYellow+"时间为:%s , 用户主机IP3 :%s"+config.ColorReset, utils.GetNormalTimeString(time.Now()), ip3)
	/*
	   操作数据库更新数字人相关信息
	*/
	err = models.UpdateDigitalPerson(&digitalPerson, session)
	if err == models.NoDigitialPersonUpdate {
		ctx.JSON(http.StatusOK, gin.H{"code": 2, "message": "数字人仅仅头像和封面更新,数字人信息未更新"})
		return
	}
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "更新数字人失败"})
		return
	}
	//判断数字人资产是否存在，如果不存在，创建数字人资产
	if digitalPersonAllInfo.SoulAsset.Id == 0 {
		var soulAsset = models.SoulAsset{
			DigitalId:       digitalPersonAllInfo.DigitalPerson.Id,
			ModelDriverType: ctx.PostForm("model_driver_type"),
			VoiceType:       ctx.PostForm("voice_type"),
		}
		err = models.CreateAsset(&soulAsset, session)
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "保存数字人资产至数据库失败"})
			return
		}
	}
	/*
	  修改数字人资产信息操作
	*/
	modelDriverType := ctx.PostForm("model_driver_type")
	voiceType := ctx.PostForm("voice_type")
	digitalPersonAllInfo.SoulAsset.ModelDriverType = modelDriverType
	digitalPersonAllInfo.SoulAsset.VoiceType = voiceType
	dp_id := digitalPersonAllInfo.DigitalPerson.Id
	asset := digitalPersonAllInfo.SoulAsset

	//判断用户是否上传模型文件夹
	// 检查上传的文件是否存在,如果上传的文件不存在，有可能用户没有上传模型文件
	form, _ := ctx.MultipartForm()
	files := form.File["mode_file"]

	if len(files) != 0 {
		//如果有文件上传，则保存模型文件
		fmt.Println("用户上传的模型文件个数：", len(files))
		FirstPath, err := UploadFolderHandler(ctx, int64(digital_id))
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{
				"code":    0,
				"message": "上传数字人模型文件失败!",
			})
			return
		}
		mode_path := "/static/asset/" + digital_PersonId + "/" + FirstPath
		asset.ModelPath = mode_path
		fmt.Println("mode_path ", mode_path)
		err = models.UpdateAsset(dp_id, asset, session)
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{
				"code":    0,
				"message": "更新数字人资产失败!",
			})
			return
		}
	} else {
		/*如果用户没有上传数字人模型文件夹,mode_path设置为空字符串*/
		fmt.Println("用户上传的模型文件个数：", len(files))
		modelDriverType := ctx.PostForm("model_driver_type")
		voiceType := ctx.PostForm("voice_type")
		digitalPersonAllInfo.SoulAsset.ModelDriverType = modelDriverType
		digitalPersonAllInfo.SoulAsset.VoiceType = voiceType
		dp_id := digitalPersonAllInfo.DigitalPerson.Id
		asset := digitalPersonAllInfo.SoulAsset
		log.Println("UpdateAsset ...before asset", asset)
		err = models.UpdateAsset(dp_id, asset, session)
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{
				"code":    0,
				"message": "更新数字人资产失败!",
			})
			return
		}
	}
	//提交事务
	err = session.Commit()
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "更新数字人失败"})
		return
	}
	log.Println("更新数字人信息成功!")
	ctx.JSON(http.StatusOK, gin.H{"code": 1, "message": "更新数字人成功"})

}

//删除数字人信息
func DropDigitalPersonByID(ctx *gin.Context) {
	/*
	   判断用户是否登录
	*/
	userID, isLogin := service.IsUserLoggedIn(ctx)
	if !isLogin {
		log.Println("用户未登录")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户未登录"})
		return
	}

	// 根据数字人id 删除数字人的逻辑
	digital_PersonId := ctx.PostForm("id")
	digital_id, err := strconv.Atoi(digital_PersonId)
	if err != nil {
		fmt.Println("数字人id转换失败:", err)
		log.Println(err.Error())
		return
	}
	/*
	  先根据前端传过来的数字人id获取数字人对象
	*/
	digitalPerson, err1 := models.GetDigitalPersonByID(int64(digital_id))
	if err1 != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "删除数字人时，获取数字人信息失败!"})
		return
	}
	//根据数字人id查询到创作者id
	authorId := digitalPerson.Author

	//判断该用户是否拥有该数字人,并获取当前登录用户的权限等级值
	level, err := models.GetUserLevel(userID)
	if err != nil {
		log.Println("修改数字人时获取用户权限失败")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "更新时获取数字人信息时，获取用户权限失败!"})
		return
	}
	if userID == authorId || level == 0 {
		// 打印转换后的结果
		//fmt.Println(int64(digital_id))
		ip := utils.ReadUserIP3(ctx.Request)
		err = models.DeleteDigitalPersonByID(int64(digital_id))
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "删除数字人失败"})
			return
		} else {

			fmt.Println("|| =============================== 删除数字人信息操作 ======================================== || ")
			log.Printf(config.ColorYellow+"时间为:%s , 用户主机IP:%s, 用户ID为: %d的用户, 删除了数字人: %s的信息。"+config.ColorReset, utils.GetNormalTimeString(time.Now()), ip, userID, digitalPerson.Name)

			fmt.Println("|| ====================================================================================== || ")

			ctx.JSON(http.StatusOK, gin.H{"code": 1, "message": "删除数字人成功"})
		}
	} else {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "对不起,当前用户没有创建该数字人,无权限执行删除操作! "})
		return
	}

}

//根据数字人名称模糊查询
func QueryLikeNameDigitalPerson(ctx *gin.Context) {
	/*
	   判断用户是否登录
	*/
	userID, isLogin := service.IsUserLoggedIn(ctx)
	if !isLogin {
		log.Println("用户未登录")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户未登录"})
		return
	}
	//这里根据用户id查询数据库，用户的状态是否为1，是否为展厅模式
	exhibitionMode, _, err := models.IsUserInExhibitionMode(userID)
	if err != nil {
		log.Println("查询用户状态值出错")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "查询用户状态值出错"})
		return
	}
	// mode为true是展厅模式
	if exhibitionMode {
		//这里固定了展厅应用的AppId为1,从配置文件读取
		appId := config.Conf.ExhibitionModeAppId
		digitalPersons, err := models.GetVisibleDigitalPersonsForUser(userID, appId)
		if err != nil {
			log.Println("查询展厅应用可见的数字人失败: ", err)
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "查询展厅应用可见的数字人失败"})
			return
		}
		ctx.JSON(http.StatusOK, gin.H{
			"code":           1,
			"message":        "查询成功",
			"digitalPersons": digitalPersons,
		})

	} else {
		authorId := userID
		//模糊查询数字人信息
		name := ctx.PostForm("name")
		persons, err := models.QueryDigitalPersons(authorId, name)
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "获取数字人失败"})
		} else {
			ctx.JSON(http.StatusOK, gin.H{
				"code":           1,
				"message":        "查询成功",
				"digitalPersons": persons,
			})
		}
	}

}

//重置数字人的神经网络记忆文件
func SoulNeuralFileReset(ctx *gin.Context) {

	/*
	   判断用户是否登录
	*/
	uid, isLogin := service.IsUserLoggedIn(ctx)
	if !isLogin {
		log.Println("用户未登录")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户未登录"})
		return
	}
	//从前端获取需要重置的数字人Id,根据数字人id查询意识流id;通过参数将意识流Id传给接口
	digital_PersonId := ctx.PostForm("id")
	/**
	  转换数字人Id为int类型, 方便后面数字人信息从数据库中查询获取
	*/
	digital_id, err := strconv.Atoi(digital_PersonId)
	if err != nil {
		fmt.Println("数字人id转换失败:", err)
		log.Println(err.Error())
		return
	}
	//从前端获取AppId
	AppId := ctx.PostForm("app_id")
	var app_id int64
	if AppId != "" {
		app_id, err = strconv.ParseInt(AppId, 10, 64)
		if err != nil {
			fmt.Println("NeuralFileReset  app_id:", app_id)
		}
	} else {
		app_id = 0
	}

	/*
	  根据用户id和数字人id，查询会话
	*/
	fmt.Println(config.ColorPurple, "digital_id:", int64(digital_id), "NeuralFileReset  app_id: ", app_id, config.ColorReset)

	conversation, err := models.GetConversationsByUserIdAndDpId(uid, int64(digital_id), app_id)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "查询会话记录失败！"})
		return
	}
	if conversation == nil {
		fmt.Println(config.ColorGreen, "重置记忆文件时，查询会话对象失败!", config.ColorReset)
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "重置记忆文件失败，未查询到对应的会话!"})
		return
	}
	SoulUrl := config.Conf.SoulUrl + "/soul/neural"

	// 封装请求参数结构体
	request := service.SoulNeuralRequest{
		Auth:    config.Conf.SoulAuth,
		Type:    2, //0下载（离魂） 1上传（还魂） 2实例化（超度）
		ISLIUid: conversation.IsliuId,
	}

	err, res_code := service.SoulNeuralFileReset(SoulUrl, request)
	if err != nil {
		log.Println("重置数字人神经网络记忆文件时失败!")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "重置数字人神经网络记忆文件时失败!"})
	}

	//uuid获取，区分应用
	Reset_UUID := ctx.PostForm("uuid")
	//查询数据库，根据数字人Id查询数字人信息
	digitalPerson, err := models.GetDigitalPersonByID(int64(digital_id))
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户与数字人创建会话时，查询数字人失败"})
		log.Println(err.Error())
		return
	}

	//响应码为1，记忆文件重置成功
	if res_code == 1 {

		ctx.JSON(http.StatusOK, gin.H{"code": 1, "message": "重置数字人神经网络记忆文件成功!"})
		chatRecordArray := database.ChatRecordArray{
			ConversationId: utils.Strval(uid) + "_" + utils.Strval(conversation.DpId) + "_" + utils.Strval(conversation.AppId),
			Timestamp:      time.Now().Unix(),
			//存个空的聊天记录数组
			Records: []database.ChatRecord{},
		}
		err = database.SaveChatRecordArray(chatRecordArray)
		if err != nil {
			log.Println("MongoDB数据库插入一条数据，err: ", err)
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "重置记忆文件,插入数据失败!"})
			return
		}
		fmt.Println(config.ColorBlue, "SoulNeural reset after ChatRecordArray  saved successfully", config.ColorReset)

		/*
		   从请求中获取uuid，如果uuid为空，表示为普通的个人与数字人聊天的清除，需要重新NewAI接口获取意识流ID
		*/

		if Reset_UUID == "" && app_id == 0 {

			//如果前端没有传uuid，参数个数为1
			apiCode, ISULU_ID, err := service.HuaSoulNewAPI(digital_PersonId)
			if err != nil {
				ctx.JSON(http.StatusOK, gin.H{"code": 0, "content": "数字人会话创建连接，失败！"})
			}
			if apiCode != 1 && ISULU_ID == "" {
				ctx.JSON(http.StatusOK, gin.H{"code": 0, "content": "创建调用数字人会话接口实例，失败！"})

			}
			if service.Manager.Clients[utils.Strval(uid)] != nil {
				service.Manager.Clients[utils.Strval(uid)].Conversation.IsliuId = ISULU_ID
			}
			fmt.Printf("更新Websocket客户端用户id为%d的意识流ID: \033[1;36m%s\033[0m\n", uid, ISULU_ID)

			conversation.Title = "用户Id为" + utils.Strval(uid) + "的用户和数字人" + digitalPerson.Name + "开始会话"
			conversation.IsliuId = ISULU_ID
			//不是应用AppId为0
			conversation.AppId = app_id
			//conversation = &models.Conversation{
			//	Uid:     uid,
			//	DpId:    int64(digital_id),
			//	Title:   "用户Id为" + utils.Strval(uid) + "的用户和数字人" + digitalPerson.Name + "开始会话",
			//	IsliuId: ISULU_ID,
			//}

			/*
			 mysql数据库的会话表更新意识流ID
			*/
			err = models.UpdateOrInsertConversation(conversation)
			if err != nil {
				ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "创建会话后，向数据库插入数据失败！"})
				return
			}

		}

		/*
		   UUID不为空，app_id不为0，表示应用数字人的记忆清除，重新newAI接口获取意识流ID
		*/
		if Reset_UUID != "" && app_id != 0 {
			fmt.Println(config.ColorCyan, "Reset_UUID : ", Reset_UUID, config.ColorReset)

			apiCode, ISULU_ID, err := service.HuaSoulNewAPI(digital_PersonId, Reset_UUID)
			if err != nil {
				ctx.JSON(http.StatusOK, gin.H{"code": 0, "content": "数字人会话创建连接，失败！"})
			}
			if apiCode != 1 && ISULU_ID == "" {
				ctx.JSON(http.StatusOK, gin.H{"code": 0, "content": "创建调用数字人会话接口实例，失败！"})

			}

			//更新Websocket客户端的意识流ID
			if service.Manager.Clients[utils.Strval(uid)] != nil {
				service.Manager.Clients[utils.Strval(uid)].Conversation.IsliuId = ISULU_ID
			}

			fmt.Printf("更新Websocket客户端用户id为%d的意识流ID: \033[1;36m%s\033[0m\n", uid, ISULU_ID)

			conversation.Title = "用户Id为" + utils.Strval(uid) + "的用户和数字人" + digitalPerson.Name + "开始会话"
			conversation.IsliuId = ISULU_ID

			//conversation = &models.Conversation{
			//	Uid:     uid,
			//	DpId:    int64(digital_id),
			//	Title:   "用户Id为" + utils.Strval(uid) + "的用户和数字人" + digitalPerson.Name + "开始会话",
			//	IsliuId: ISULU_ID,
			//}
			//把应用的id赋值给会话
			conversation.AppId = app_id

			/*
			 mysql数据库的会话表更新意识流ID
			*/
			err = models.UpdateOrInsertConversation(conversation)
			if err != nil {
				ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "创建会话后，向数据库插入数据失败！"})
				return
			}

		}
	}
	//重置数字人神经网络记忆文件失败
	if res_code == -1 {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "重置数字人神经网络记忆文件失败!"})
	}

}

//重置多个数字人的神经网络记忆文件
func SoulNeuralFileResetDps(ctx *gin.Context) {

	/*
	   判断用户是否登录
	*/
	uid, isLogin := service.IsUserLoggedIn(ctx)
	if !isLogin {
		log.Println("用户未登录")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户未登录"})
		return
	}
	//从前端获取需要重置的数字人Id,根据数字人id查询意识流id;通过参数将意识流Id传给接口
	DpIds := ctx.PostForm("DpIds")
	// 声明数字人id数组，意识流id数组，数字人名称数组，会话主题字符串
	DpIdArr := []int64{}
	digitalPersonArr := []*models.DigitalPerson{}
	var IsLiuIds []string
	var ConversationTitle string
	var DpNames []string

	// 分割字符串，得到单独的数值字符串
	DpIdsSplit := strings.Split(DpIds, ",")
	for _, DpIdStr := range DpIdsSplit {
		// 将字符串转换为 int64 类型
		dpId, err := strconv.ParseInt(DpIdStr, 10, 64)
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "数字人id类型转换出错"})
			//continue
			return
		}
		// 将转换后的数值添加到数组
		DpIdArr = append(DpIdArr, dpId)
		//查询数据库，根据数字人Id查询数字人信息
		digitalPerson, err := models.GetDigitalPersonByID(dpId)
		if err != nil {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户与数字人创建会话时，查询数字人失败"})
			log.Println(err.Error())
			return
		}
		//fmt.Println("digitalPerson: ", digitalPerson)
		DpNames = append(DpNames, digitalPerson.Name)
		digitalPersonArr = append(digitalPersonArr, digitalPerson)

	}

	//从前端获取AppId
	AppId := ctx.PostForm("app_id")
	var app_id int64
	if AppId != "" {
		app_id, err := strconv.ParseInt(AppId, 10, 64)
		if err != nil {
			fmt.Println("NeuralFileReset  app_id:", app_id)
		}
	} else {
		app_id = 0
	}

	/*
	  根据用户id和数字人id，查询多个数字人会话记录
	*/
	fmt.Println(config.ColorPurple, "digital_id:", DpIdArr, "NeuralFileReset  app_id: ", app_id, config.ColorReset)
	// 根据用户id和数字人id，查询多个数字人会话记录
	conversation, err := models.QueryConversationsByUserIdAndDpId(uid, DpIdArr, app_id)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "查询多数字人会话记录失败！"})
		return
	}
	if conversation == nil {
		fmt.Println(config.ColorGreen, "重置记忆文件时，查询多数字人会话记录失败!", config.ColorReset)
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "重置记忆文件失败，查询多数字人会话记录失败!"})
		return
	}
	SoulUrl := config.Conf.SoulUrl + "/soul/neural"
	var SoulReset_resCode int

	for i := 0; i < len(DpIdArr); i++ {
		// 封装请求参数结构体
		request := service.SoulNeuralRequest{
			Auth:    config.Conf.SoulAuth,
			Type:    2, //0下载（离魂） 1上传（还魂） 2实例化（超度）
			ISLIUid: conversation.IsliuIds[i],
		}

		err, SoulReset_resCode = service.SoulNeuralFileReset(SoulUrl, request)
		if err != nil {
			log.Println("重置数字人神经网络记忆文件时失败!")
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "重置数字人神经网络记忆文件时失败!"})
		}
	}

	//uuid获取，区分应用
	Reset_UUID := ctx.PostForm("uuid")

	dpIdsStr := utils.Int64SliceToStringSlice(conversation.DpIds)
	conversation_Id := utils.Strval(conversation.Uid) + "_" + strings.Join(dpIdsStr, ",") + "_" + utils.Strval(conversation.AppId)
	//拼接会话主题
	ConversationTitle = "用户Id为" + utils.Strval(conversation.Uid) + "的用户和数字人" + strings.Join(DpNames, "和") + "开始会话"
	//响应码为1，记忆文件重置成功
	if SoulReset_resCode == 1 {

		chatRecordArray := database.ChatRecordArray{
			ConversationId: conversation_Id,
			Timestamp:      time.Now().Unix(),
			//存个空的聊天记录数组
			Records: []database.ChatRecord{},
		}
		err = database.SaveChatRecordArray(chatRecordArray)
		if err != nil {
			log.Println("MongoDB数据库插入一条数据，err: ", err)
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "重置记忆文件,插入数据失败!"})
			return
		}
		fmt.Println(config.ColorBlue, "SoulNeural reset after ChatRecordArray  saved successfully", config.ColorReset)

		/*
		   从请求中获取uuid，如果uuid为空，表示为普通的个人与数字人聊天的清除，需要重新NewAI接口获取意识流ID
		*/

		if Reset_UUID == "" && app_id == 0 {

			//如果前端没有传uuid，参数个数为1
			for i := 0; i < len(DpIdArr); i++ {
				apiCode, ISULU_ID, err := service.HuaSoulNewAPI(utils.Strval(DpIdArr[i]))
				if err != nil {
					ctx.JSON(http.StatusOK, gin.H{"code": 0, "content": "数字人会话创建连接，失败！"})
				}
				if apiCode != 1 && ISULU_ID == "" {
					ctx.JSON(http.StatusOK, gin.H{"code": 0, "content": "创建调用数字人会话接口实例，失败！"})

				} else {

					IsLiuIds = append(IsLiuIds, ISULU_ID)
				}

			}
			if service.DpsManager.Clients[utils.Strval(uid)] != nil {
				service.DpsManager.Clients[utils.Strval(uid)].DpConversations.IsliuIds = IsLiuIds
			}
			fmt.Printf("更新Websocket客户端用户id为%d的意识流ID: \033[1;36m%s\033[0m\n", uid, IsLiuIds)
			// 构建多数字人会话对象
			conversation.Title = ConversationTitle
			conversation.IsliuIds = IsLiuIds
			//conversation = &models.DpConversations{
			//	Uid:      uid,
			//	DpIds:    DpIdArr,
			//	Title:    ConversationTitle,
			//	IsliuIds: IsLiuIds,
			//	AppId:    app_id,
			//}

			//不是应用AppId为0
			conversation.AppId = app_id
			/*
			 mysql数据库的会话表更新意识流ID
			*/
			err = models.UpdateOrInsertDpsConversations(conversation)
			if err != nil {
				ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "创建会话后，向数据库插入数据失败！"})
				return
			}

		}

		/*
		   UUID不为空，app_id不为0，表示应用数字人的记忆清除，重新newAI接口获取意识流ID
		*/
		if Reset_UUID != "" && app_id != 0 {
			fmt.Println(config.ColorCyan, "Reset_UUID : ", Reset_UUID, config.ColorReset)

			for i := 0; i < len(DpIdArr); i++ {
				apiCode, ISULU_ID, err := service.HuaSoulNewAPI(utils.Strval(DpIdArr[i]), Reset_UUID)
				if err != nil {
					ctx.JSON(http.StatusOK, gin.H{"code": 0, "content": "数字人会话创建连接，失败！"})
				}
				if apiCode != 1 && ISULU_ID == "" {
					ctx.JSON(http.StatusOK, gin.H{"code": 0, "content": "创建调用数字人会话接口实例，失败！"})

				} else {

					IsLiuIds = append(IsLiuIds, ISULU_ID)
				}

			}
			//更新Websocket客户端的意识流ID
			if service.DpsManager.Clients[utils.Strval(uid)] != nil {
				service.DpsManager.Clients[utils.Strval(uid)].DpConversations.IsliuIds = IsLiuIds
			}
			fmt.Printf("更新Websocket客户端用户id为%d的意识流ID: \033[1;36m%s\033[0m\n", uid, IsLiuIds)

			// 构建多数字人会话对象
			conversation.Title = ConversationTitle
			conversation.IsliuIds = IsLiuIds
			conversation.AppId = app_id
			//conversation = &models.DpConversations{
			//	Uid:      uid,
			//	DpIds:    DpIdArr,
			//	Title:    ConversationTitle,
			//	IsliuIds: IsLiuIds,
			//	AppId:    app_id,
			//}

			/*
			 mysql数据库的会话表更新意识流ID
			*/
			err = models.UpdateOrInsertDpsConversations(conversation)
			if err != nil {
				ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "创建会话后，向数据库插入数据失败！"})
				return
			}

		}
		ctx.JSON(http.StatusOK, gin.H{"code": 1, "message": "重置数字人神经网络记忆文件成功!"})
	}
	//重置数字人神经网络记忆文件失败
	if SoulReset_resCode == -1 {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "重置数字人神经网络记忆文件失败!"})
		return
	}

}

//查询用户与那些数字人进行过聊天会话
func QueryUserToDpConversation(ctx *gin.Context) {
	/*
	   判断用户是否登录
	*/
	uid, isLogin := service.IsUserLoggedIn(ctx)
	if !isLogin {
		log.Println("用户未登录")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户未登录"})
		return
	}
	user, err1 := models.GetUserByID(uid)
	if err1 != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "查询用户已聊天的数字人会话，获取用户名称失败！"})
		return
	}
	//fmt.Println(user.Username)

	digitalPersons, err := models.GetDigitalPersonsByUserID(uid)

	//fmt.Println("根据用户ID查询对应的数字人ID和名字: ", digitalPersons)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "查询用户已聊天的数字人会话，查询失败！"})
		return
	}

	info := models.UserDigitalPersonInfo{
		UserID:         uid,
		UserName:       user.Username,
		DigitalPersons: digitalPersons,
	}

	fmt.Println(" UserConversationDPInfo 获取用户聊天过的数字人个数 : ", len(info.DigitalPersons))

	ctx.JSON(http.StatusOK, gin.H{"code": 1, "message": info})

}

//根据用户id和数字人id查询该用户与数字人聊天的历史记录
func QueryUserAndDigitalPersonHistoryChatById(ctx *gin.Context) {
	/*
	   判断用户是否登录
	*/
	uid, isLogin := service.IsUserLoggedIn(ctx)
	if !isLogin {
		log.Println("用户未登录")
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户未登录"})
		return
	}
	//从前端获取需数字人id
	digital_PersonIds := ctx.PostForm("id")
	if digital_PersonIds == "" {
		ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "数字人id不能为空"})
		return
	}
	appId := ctx.PostForm("app_id")
	var app_id int64
	if appId != "" {
		var err error
		app_id, err = strconv.ParseInt(appId, 10, 64)
		if err != nil {
			fmt.Println("app_id 不为空:", app_id)
		}
	} else {
		app_id = 0
	}

	var mergeAll bool
	if ctx.PostForm("mergeAll") == "" || ctx.PostForm("mergeAll") == "false" {
		mergeAll = false
	}
	if ctx.PostForm("mergeAll") == "true" {
		mergeAll = true
	}
	chatRecordArray, err := database.GetChatHistoryLatest(utils.Strval(uid), digital_PersonIds, utils.Strval(app_id), mergeAll)
	if err != nil {
		if err == database.ErrNotFound {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "未找到该用户与数字人的会话聊天记录"})
		} else {
			ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "查询失败"})
		}
		return
	}

	ctx.JSON(http.StatusOK, gin.H{"code": 1, "message": "查询成功!", "chatRecordInfo": chatRecordArray})
	//fmt.Println(config.ColorGreen, "chatRecordArray query  history chat of successfully: ", chatRecordArray, config.ColorReset)
}
