package datasource

import (
	"WorldEpcho/src/config"
	"fmt"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	//"gopkg.in/mgo.v2/bson"
	"go.mongodb.org/mongo-driver/bson"
	"log"
	"time"
)

// ChatRecord 表示聊天记录的结构体
type WorldChatRecord struct {
	//ID         bson.ObjectId          `bson:"_id,omitempty"`
	SenderId   int64                  `bson:"SenderId"`
	WorldName  string                 `bson:"worldName"`
	Timestamp  int64                  `bson:"timestamp"`
	Message    string                 `bson:"message"`
	WObj       map[string]interface{} `bson:"w_obj"`      // 新增字段，表示消息发送者的聊天表情状态
	SenderType string                 `bson:"senderType"` // 新增字段，表示消息发送方类型
}

// 聊天记录数组
type WorldChatRecordArray struct {
	ConversationId string            `bson:"conversationId"`
	Timestamp      int64             `bson:"timestamp"`
	Records        []WorldChatRecord `bson:"records"`
}

//历史聊天记录数组
type WorldChatHistoryRecordArray struct {
	WorldHistoryArrays []WorldChatRecordArray
}

//添加全局变量
const (
	DatabaseName_world   = "world_chat_db"
	CollectionName_world = "world_chat_records"
)

//保存单条聊天记录
func SaveWorldChatRecord(record WorldChatRecordArray) error {
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	_, err := collection.InsertOne(ctx, record)
	if err != nil {
		return err
	}

	return nil
}

// 保存聊天记录数组
func SaveWorldChatRecordArray(recordArray WorldChatRecordArray) (int64, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	// 获取要操作的集合
	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	// 插入 ChatRecordArray
	_, err := collection.InsertOne(ctx, recordArray)
	if err != nil {
		return 0, err
	}
	return recordArray.Timestamp, nil

}

// 根据会话Id,查询聊天记录
func GetWorldChatRecordByConversationID(conversationID string) (*WorldChatRecord, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	// 获取要操作的集合
	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	// 查询会话记录
	filter := bson.M{"conversationId": conversationID}

	var chatRecordArray WorldChatRecordArray
	err := collection.FindOne(ctx, filter).Decode(&chatRecordArray)
	if err == mongo.ErrNoDocuments {
		return nil, nil
	} else if err != nil {
		return nil, fmt.Errorf("查询记录失败: %v", err)
	}

	if len(chatRecordArray.Records) > 0 {
		return &chatRecordArray.Records[len(chatRecordArray.Records)-1], nil
	} else {
		return nil, nil
	}

}

//添加用户和世界的聊天记录到会话表
func AddWorldChatRecordToConversation(conversationID string, chatRecords []WorldChatRecord) error {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	// 获取要操作的集合
	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)
	// 创建要添加的记录
	// 更新时间戳并添加新的聊天记录
	update := bson.M{
		//"$set":  bson.M{"timestamp": time.Now().Unix()},          // 更新整个会话的时间戳
		"$push": bson.M{"records": bson.M{"$each": chatRecords}}, // 添加新的聊天记录
	}
	// 根据会话 Id 更新记录
	_, err := collection.UpdateOne(ctx, bson.M{"conversationId": conversationID}, update)
	if err != nil {
		return err
	}
	return nil
}

//查询用户与世界的历史聊天记录
func GetWorldChatHistory(userID, worldID string) (WorldChatRecordArray, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	filter := bson.M{"conversationId": userID + "_" + worldID}

	var chatRecordArray WorldChatRecordArray
	log.Println("找到了匹配的记录")

	err := collection.FindOne(ctx, filter).Decode(&chatRecordArray)

	if err == mongo.ErrNoDocuments {
		return chatRecordArray, ErrNotFound
	} else if err != nil {
		log.Printf("Error in GetChatHistory: %v", err)
		return chatRecordArray, err
	}

	return chatRecordArray, nil

}

//获取最新的聊天记录数组
func GetWorldChatHistoryLatest1(userID, worldID string) (WorldChatRecordArray, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	// 设置查询过滤器
	filter := bson.M{"conversationId": userID + "_" + worldID}
	// 设置排序参数，按照时间戳降序排序
	//options := options.FindOne().SetSort(bson.D{{"timestamp", -1}})
	options := options.FindOne().SetSort(bson.D{{"timestamp", -1}})

	//opts := bson.D{{"timestamp", -1}}

	var chatRecordLatest WorldChatRecordArray
	log.Println(config.ColorBlue, "正在查询最新的会话记录", config.ColorReset)

	err := collection.FindOne(ctx, filter, options).Decode(&chatRecordLatest)
	//err := collection.Find(ctx,filter).Sort(opts).One(&chatRecordArray)

	if err == mongo.ErrNoDocuments {
		log.Println(config.ColorYellow, "没有找到记录", config.ColorReset)
		return chatRecordLatest, ErrNotFound
	} else if err != nil {
		log.Printf(config.ColorRed, "在 GetChatHistory 中发生错误: %v", err, config.ColorReset)
		return chatRecordLatest, err
	}
	//fmt.Println(config.ColorYellow, "最近一次聊天记录", chatRecordLatest, config.ColorReset)

	return chatRecordLatest, nil
}

// GetChatHistoryLatest 获取最新的聊天记录，根据mergeAll参数获取最新一条或全部记录
//
func GetWorldChatHistoryLatest(userID, worldID string, mergeAll bool) (WorldChatRecordArray, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName).Collection(CollectionName)

	// 设置查询过滤器
	filter := bson.M{"conversationId": userID + "_" + worldID}

	var worldChatRecordLatest WorldChatRecordArray

	if mergeAll {
		// 使用 GetAllHistoryChatRecords 函数获取所有记录
		allRecords, err := GetAllWorldChatHistoryChatRecords(userID, worldID)
		if err != nil {
			log.Printf("获取全部聊天记录时出错: %v\n", err)
			return WorldChatRecordArray{}, err
		}
		// 合并所有记录到一个数组中
		var mergedRecords WorldChatRecordArray
		mergedRecords.ConversationId = userID + "_" + worldID
		for _, recordArray := range allRecords {
			mergedRecords.Records = append(mergedRecords.Records, recordArray.Records...)
		}

		if len(mergedRecords.Records) > 0 {
			mergedRecords.Timestamp = mergedRecords.Records[len(mergedRecords.Records)-1].Timestamp
		}
		return mergedRecords, nil

	} else {
		// 只获取最新的一条记录
		result := collection.FindOne(ctx, filter, options.FindOne().SetSort(bson.D{{"timestamp", -1}}))
		if err := result.Decode(&worldChatRecordLatest); err != nil {
			if err == mongo.ErrNoDocuments {
				log.Println(config.ColorYellow, "没有找到记录", config.ColorReset)
				return worldChatRecordLatest, ErrNotFound
			}
			log.Printf(config.ColorRed, "在查询最新记录时发生错误: %v", err, config.ColorReset)
			return worldChatRecordLatest, err
		}
		// 必须设置Records为仅包含这一条最新记录
		if len(worldChatRecordLatest.Records) > 0 {
			worldChatRecordLatest.Records = worldChatRecordLatest.Records[:1]
		}
	}

	log.Println(config.ColorBlue, "查询会话记录成功", config.ColorReset)
	return worldChatRecordLatest, nil
}

// GetAllHistoryChatRecords 获取特定用户和数字人的某应用的所有聊天记录，并按时间顺序合并到一个数组中
func GetAllWorldChatHistoryChatRecords(userID, worldID string) ([]WorldChatRecordArray, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)
	collection := client.Database(DatabaseName).Collection(CollectionName)

	// 构建查询
	filter := bson.M{"conversationId": bson.M{"$eq": userID + "_" + worldID}}
	opts := options.Find().SetSort(bson.D{{"timestamp", 1}}) // 按时间戳升序排序

	// 查询数据
	cursor, err := collection.Find(ctx, filter, opts)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			log.Println("没有找到聊天记录")
			return nil, err
		}
		log.Printf("在执行 MongoDB 查找操作时出错: %s\n", err)
		return nil, err
	}
	defer cursor.Close(ctx)

	// 解析数据
	var WorldRecordArray []WorldChatRecordArray
	if err := cursor.All(ctx, &WorldRecordArray); err != nil {
		log.Printf("解析聊天记录出错: %s\n", err)
		return nil, err
	}

	return WorldRecordArray, nil

}

func QueryAllWorldChatRecordArrays(userID, worldID string) ([]WorldChatRecordArray, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	// 构建查询
	filter := bson.M{"conversationId": bson.M{"$eq": userID + "_" + worldID}}
	//filter := bson.M{"conversationId": conversationId}
	opts := options.Find().SetSort(bson.D{{"timestamp", 1}}) // 按时间戳升序排序

	// 查询数据
	cursor, err := collection.Find(ctx, filter, opts)
	if err != nil {
		log.Printf("在查询数据库时遇到错误: %s\n", err)
		return nil, err
	}
	defer cursor.Close(ctx)

	// 解析数据
	var chatRecordArrays []WorldChatRecordArray
	if err := cursor.All(ctx, &chatRecordArrays); err != nil {
		log.Printf("解析聊天记录数据时出错: %s\n", err)
		return nil, err
	}

	return chatRecordArrays, nil
}

//根据会话ID和时间戳查询具体的历史聊天记录
func GetChatRecordsByConversationIdAndTimestamp(userID, worldID string, timestamp int64) (*WorldChatRecordArray, error) {
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	// Constructing the filter
	filter := bson.M{
		"conversationId": userID + "_" + worldID,
		"timestamp":      timestamp,
	}

	var result WorldChatRecordArray
	err := collection.FindOne(ctx, filter).Decode(&result)
	if err != nil {
		return nil, err
	}

	return &result, nil
}

func FetchAllChatRecordsByConversationID(userID, worldID string) (*WorldChatHistoryRecordArray, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	// 构建查询
	filter := bson.M{"conversationId": bson.M{"$eq": userID + "_" + worldID}}
	opts := options.Find().SetSort(bson.D{{"timestamp", 1}}) // 按时间戳升序排序

	// 查询数据
	cursor, err := collection.Find(ctx, filter, opts)
	if err != nil {
		log.Printf("在查询数据库时遇到错误: %s\n", err)
		return nil, err
	}
	defer cursor.Close(ctx)

	// 解析数据
	var chatRecordArrays []WorldChatRecordArray
	if err := cursor.All(ctx, &chatRecordArrays); err != nil {
		log.Printf("解析聊天记录数据时出错: %s\n", err)
		return nil, err
	}

	// 封装到 WorldChatHistoryRecordArray 结构中
	historyRecordArray := &WorldChatHistoryRecordArray{
		WorldHistoryArrays: chatRecordArrays,
	}

	return historyRecordArray, nil
}

func FetchAllChatRecordsByConversationID2(userID, worldID string) (*WorldChatHistoryRecordArray, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	// 构建查询
	filter := bson.M{"conversationId": bson.M{"$eq": userID + "_" + worldID}}
	opts := options.Find().SetSort(bson.D{{"timestamp", 1}}) // 按时间戳升序排序

	// 查询数据
	cursor, err := collection.Find(ctx, filter, opts)
	if err != nil {
		log.Printf("在查询数据库时遇到错误: %s\n", err)
		return nil, err
	}
	defer cursor.Close(ctx)

	// 解析数据
	var chatRecordArrays []WorldChatRecordArray
	if err := cursor.All(ctx, &chatRecordArrays); err != nil {
		log.Printf("解析聊天记录数据时出错: %s\n", err)
		return nil, err
	}

	// 创建 WorldChatHistoryRecordArray
	historyRecordArray := &WorldChatHistoryRecordArray{}

	// 遍历每条记录，并将其单独封装到一个 WorldChatRecordArray 中
	for _, recordArray := range chatRecordArrays {
		historyRecordArray.WorldHistoryArrays = append(historyRecordArray.WorldHistoryArrays, WorldChatRecordArray{
			ConversationId: recordArray.ConversationId,
			Timestamp:      recordArray.Timestamp,
			Records:        recordArray.Records,
		})
	}
	return historyRecordArray, nil
}

//获取最近的聊天记录数组,如果没有最近聊天记录数组，则取倒数第二条，也就是上上一条
func GetWorldChatHistoryLatest2(userID, worldID string) (WorldChatRecordArray, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	// 设置查询过滤器
	filter := bson.M{"conversationId": userID + "_" + worldID}
	// 设置排序参数，按照时间戳降序排序，并限制结果数量为最新的两条记录
	options := options.Find().SetSort(bson.D{{Key: "timestamp", Value: -1}}).SetLimit(2)

	var chatRecords []WorldChatRecordArray
	log.Println(config.ColorBlue, "正在查询最新的会话记录", config.ColorReset)

	cursor, err := collection.Find(ctx, filter, options)
	if err != nil {
		log.Printf(config.ColorRed, "在查询聊天历史时发生错误: %v", err, config.ColorReset)
		return WorldChatRecordArray{}, err
	}
	defer cursor.Close(ctx)

	if err = cursor.All(ctx, &chatRecords); err != nil {
		log.Printf(config.ColorRed, "解析聊天记录错误: %v", err, config.ColorReset)
		return WorldChatRecordArray{}, err
	}

	if len(chatRecords) == 0 {
		log.Println(config.ColorYellow, "没有找到记录", config.ColorReset)
		return WorldChatRecordArray{}, ErrNotFound
	}

	// 选择适当的记录返回
	var result WorldChatRecordArray
	if len(chatRecords[0].Records) > 0 {
		result = chatRecords[0]
	} else if len(chatRecords) > 1 && len(chatRecords[1].Records) > 0 {
		result = chatRecords[1]
	} else {
		log.Println(config.ColorYellow, "最新两条记录均无内容", config.ColorReset)
		return WorldChatRecordArray{}, ErrNotFound
	}

	return result, nil
}

//获取最新的聊天记录,并从聊天记录数组中获取最后一条
func GetWorldChatHistoryRecordLatest(userID, worldID string) (WorldChatRecord, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	//设置查询过滤器
	filter := bson.M{"conversationId": userID + "_" + worldID}

	// 设置排序参数，按照时间戳降序排序
	//options := options.FindOne().SetSort(bson.D{{"timestamp", -1}})
	options := options.FindOne().SetSort(bson.D{{"timestamp", -1}})

	//opts := bson.D{{"timestamp", -1}}

	var chatRecordArray WorldChatRecordArray
	log.Println(config.ColorBlue, "正在查询最新的会话记录", config.ColorReset)

	err := collection.FindOne(ctx, filter, options).Decode(&chatRecordArray)

	if err == mongo.ErrNoDocuments {
		log.Println(config.ColorRed, "没有找到记录", config.ColorReset)
		return WorldChatRecord{}, ErrNotFound
	} else if err != nil {
		log.Printf(config.ColorRed, "在 GetChatHistoryRecordLatest 中发生错误: %v", err, config.ColorReset)
		return WorldChatRecord{}, err
	}
	//fmt.Println(config.ColorYellow, "最近一次聊天记录", chatRecordArray, config.ColorReset)
	//最后一次聊天记录
	var latestRecord WorldChatRecord
	var foundBotRecord bool // New variable to track if we have found a bot record

	if len(chatRecordArray.Records) > 0 {
		for _, record := range chatRecordArray.Records {
			if record.SenderType == "world" && (!foundBotRecord || record.Timestamp > latestRecord.Timestamp) {
				latestRecord = record
				foundBotRecord = true // We have found a record with senderType "bot"
			}
		}
	}
	if !foundBotRecord {
		log.Println(config.ColorRed, "没有找到该世界的聊天记录", config.ColorReset)
		return WorldChatRecord{}, ErrNotFound
	}
	fmt.Println(config.ColorYellow, "最新的世界聊天记录", latestRecord, config.ColorReset)
	fmt.Println(config.ColorGreen, "最新的世界聊天记录", latestRecord.WObj, config.ColorReset)
	return latestRecord, nil
}

//更新最近的聊天记录
func UpdateWorldChatLatest(conversationID string, chatRecords []WorldChatRecord) error {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	// 设置查询过滤器
	filter := bson.M{"conversationId": conversationID}
	//定义一个变量保存当前最大的时间戳
	//var maxTimeStamp int64 = 0

	// 设置排序参数，按照时间戳降序排序
	options := options.FindOneAndUpdate().SetSort(bson.D{{"timestamp", -1}})

	// 更新操作
	/*
		update := bson.M{
			"$push": bson.M{"records": record},
		}
	*/
	update := bson.M{
		"$push": bson.M{"records": bson.M{"$each": chatRecords}},
	}

	// 执行更新操作

	result := collection.FindOneAndUpdate(ctx, filter, update, options)
	if result.Err() != nil {
		log.Printf(config.ColorRed, "在 UpdateChatLatest 中发生错误: %v", result.Err(), config.ColorReset)
		return result.Err()
	}

	log.Println(config.ColorGreen, "成功更新最新的会话记录", config.ColorReset)
	return nil
}

//更新最近的聊天记录2
func UpdateWorldChatLatest2(conversationID string, chatRecords []WorldChatRecord) (int64, error) {
	// 连接 MongoDB
	client, ctx, cancel := setupMongoDB()
	defer cancel()
	defer client.Disconnect(ctx)

	collection := client.Database(DatabaseName_world).Collection(CollectionName_world)

	// 设置查询过滤器
	filter := bson.M{"conversationId": conversationID}

	// 设置排序参数，按照时间戳降序排序，并只返回最新的记录
	option := options.FindOne().SetSort(bson.D{{"timestamp", -1}}).SetProjection(bson.M{"timestamp": 1})

	// 获取最大时间戳
	var result struct {
		Timestamp int64 `bson:"timestamp"`
	}
	err := collection.FindOne(ctx, filter, option).Decode(&result)
	if err != nil {
		log.Printf("在查询最大时间戳时发生错误: %v", err)
		return 0, err
	}

	// 设置排序参数，按照时间戳降序排序
	option2 := options.FindOneAndUpdate().SetSort(bson.D{{"timestamp", -1}})

	// 更新操作
	update := bson.M{
		"$push": bson.M{"records": bson.M{"$each": chatRecords}},
	}

	// 执行更新操作

	result1 := collection.FindOneAndUpdate(ctx, filter, update, option2)
	if result1.Err() != nil {
		log.Printf(config.ColorRed, "在 UpdateChatLatest 中发生错误: %v", result1.Err(), config.ColorReset)
		return 0, result1.Err()
	}

	log.Println("成功更新最新的会话记录")
	return result.Timestamp, nil
}

//保存聊天会话到MongoDB数据库
func SaveWorldChatRecordMongoDB(conversationId string, senderId int64, worldName, message string, WObj map[string]interface{}, senderType string) (int64, error) {
	chatRecord, err := GetWorldChatRecordByConversationID(conversationId)
	if err != nil {
		log.Println(config.ColorRed, "保存聊天会话到MongoDB数据库，err: ", err, config.ColorReset)
		return 0, err
	}
	//timeString := utils.GetNormalTimeString(time.Now())
	//定义一个变量保存最大的聊天记录时间戳
	var maxTimeStamp int64

	// 如果数据库中，聊天记录表没有这个聊天记录则插入一条
	if chatRecord == nil {
		worldChatRecordArray := WorldChatRecordArray{
			ConversationId: conversationId,
			Timestamp:      time.Now().Unix(),
			Records: []WorldChatRecord{
				{SenderId: senderId, WorldName: worldName, Timestamp: time.Now().Unix(), Message: message, WObj: WObj, SenderType: senderType},
			},
		}
		maxTimeStamp, err = SaveWorldChatRecordArray(worldChatRecordArray)
		if err != nil {
			log.Println(config.ColorRed, "MongoDB数据库插入一条数据，err: ", err, config.ColorReset)
			return 0, err
		}
		fmt.Println(config.ColorGreen, "ChatRecordArray  first saved successfully", config.ColorReset)
		return maxTimeStamp, nil
	} else {
		// 如果数据库中已经存在聊天记录，则更新记录
		/*
			chatRecords := []ChatRecord{
				{SenderId: senderId, Timestamp: time.Now().Unix(), Message: message, Status: status, SenderType: senderType},
			}
		*/
		chatRecords := []WorldChatRecord{
			{
				SenderId:   senderId,
				WorldName:  worldName,
				Timestamp:  time.Now().Unix(),
				Message:    message,
				WObj:       WObj,
				SenderType: senderType,
			},
		}
		//err := AddChatRecordToConversation(conversationId, chatRecords)
		maxTimeStamp, err = UpdateWorldChatLatest2(conversationId, chatRecords)
		if err != nil {
			log.Println(config.ColorRed, "MongoDB数据库更新一条数据，err: ", err, config.ColorReset)
			return 0, err
		}
		fmt.Println("maxTimeStamp ===> ", maxTimeStamp)
		fmt.Println(config.ColorGreen, "ChatRecordArray saveAndUpdate successfully", config.ColorReset)
	}

	return maxTimeStamp, nil
}
