package api

import (
	"context"
	"copter-train/db/model"
	"copter-train/db/repo"
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
)

// 本年每月学习时长
func StatisticsLearnProcess(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	// 如果没有uid参数,则查询当前用户的
	uid := c.Query("uid")
	if len(uid) == 0 {
		uid = apictx.User.ID
	}
	_type := c.Query("type")
	// 如果没有年份参数,则查询当前年份的
	_year := c.Query("year")
	year := 2024
	if len(_year) == 0 {
		year = time.Now().Year()
	} else {
		year_, err := strconv.Atoi(_year)
		if err != nil {
			return nil, errors.New("year参数错误")
		}
		year = year_
	}
	fmt.Println("year:", year)
	fmt.Println("type", _type)

	colls := apictx.CreateRepoCtx().Client.GetDbCollection(db, repo.CollectionLearnLog)
	return AggregateMonthlyLearnTime(colls, uid, _type, year)

}

// 整个模块的学习时长 不需要cid约束
func AggregateMonthlyLearnTime(colls *mongo.Collection, uid string, learnType string, year int) ([]bson.M, error) {
	chinaTimeZone := time.FixedZone("CST", 8*60*60) // 中国时区
	match := bson.D{
		{Key: "uid", Value: uid},
		{Key: "createTime", Value: bson.D{
			{Key: "$gte", Value: time.Date(year, time.January, 1, 0, 0, 0, 0, chinaTimeZone)},
			{Key: "$lt", Value: time.Date(year+1, time.January, 1, 0, 0, 0, 0, chinaTimeZone)},
		}},
	}

	// 检查 learnType 是否存在
	if len(learnType) > 0 {
		// 如果存在，添加到查询条件中
		match = append(match, bson.E{Key: "type", Value: learnType})
	}

	pipeline := mongo.Pipeline{
		{bson.E{Key: "$match", Value: match}},
		// 将 createTime 字段分解为年和月
		{
			{Key: "$addFields", Value: bson.D{
				// {"year", bson.D{{"$year", bson.D{{"$add", []interface{}{"$createTime", 8 * 60 * 60 * 1000}}}}}},
				{Key: "month", Value: bson.D{{Key: "$month", Value: bson.D{{Key: "$add", Value: []interface{}{"$createTime", 8 * 60 * 60 * 1000}}}}}},
			}},
		},
		// 按年和月分组，并计算每个月的正确和错误数量
		{
			{Key: "$group", Value: bson.D{
				{Key: "_id", Value: "$month"},
				{Key: "totalLearnTime", Value: bson.D{
					{Key: "$sum", Value: "$learnTime"},
				}},
			}},
		},
		{
			{Key: "$sort", Value: bson.D{
				{Key: "_id", Value: 1},
			}},
		},
	}

	cursor, err := colls.Aggregate(context.TODO(), pipeline)
	if err != nil {
		return nil, err
	}

	var results []bson.M
	if err = cursor.All(context.TODO(), &results); err != nil {
		return nil, err
	}

	return results, nil
}

// 个人:上次学习时长
// 获取最新一条数据
func StatisticsLastLearnTime(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	// 如果没有uid参数,则查询当前用户的
	uid := c.Query("uid")
	if len(uid) == 0 {
		uid = apictx.User.ID
	}

	learnLog := &model.LearnLog{}
	found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
		Db:          db,
		CollectName: repo.CollectionLearnLog,
		Query:       repo.Map{"uid": uid},
		Sort:        bson.M{"createTime": -1},
	}, learnLog)
	if err != nil {
		return nil, err
	}
	if !found {
		return 0, nil
	}
	return learnLog.LearnTime, nil
}

// 个人:用户总学习时长
func StatisticsTotalLearnTime(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	// 如果没有uid参数,则查询当前用户的
	uid := c.Query("uid")
	if len(uid) == 0 {
		uid = apictx.User.ID
	}

	colls := apictx.CreateRepoCtx().Client.GetDbCollection(db, repo.CollectionLearnLog)
	return AggregateTotalLearnTime(colls, uid)

}

// 查询用户学习总时长
func AggregateTotalLearnTime(colls *mongo.Collection, uid string) (int, error) {
	pipeline := mongo.Pipeline{
		{
			{Key: "$match", Value: bson.D{
				{Key: "uid", Value: uid},
			}},
		},
		{
			{Key: "$group", Value: bson.D{
				{Key: "_id", Value: "$uid"},
				{Key: "totalLearnTime", Value: bson.D{
					{Key: "$sum", Value: "$learnTime"},
				}},
			}},
		},
	}

	cursor, err := colls.Aggregate(context.TODO(), pipeline)
	if err != nil {
		return 0, err
	}

	var results []bson.M
	if err = cursor.All(context.TODO(), &results); err != nil {
		return 0, err
	}

	if len(results) > 0 {
		if v, ok := results[0]["totalLearnTime"].(int32); ok {
			return int(v), nil
		}
		return 0, nil
	}
	return 0, nil
}

// 个人: 获取最后一场考试的成绩
func StatisticsLastExeamScore(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	// 如果没有uid参数,则查询当前用户的
	uid := c.Query("uid")
	if len(uid) == 0 {
		uid = apictx.User.ID
	}

	exeamLog := &model.ExeamLog{}
	found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
		Db:          db,
		CollectName: repo.CollectionExeamLog,
		Query:       repo.Map{"uid": uid},
		Sort:        bson.M{"createTime": -1},
	}, exeamLog)
	if err != nil {
		return nil, err
	}
	if !found {
		return 0, nil
	}
	fmt.Println(exeamLog)
	return exeamLog.Score, nil
}

// 个人: 获取历史最好成绩
func StatisticsBestExeamScore(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	// 如果没有uid参数,则查询当前用户的
	uid := c.Query("uid")
	if len(uid) == 0 {
		uid = apictx.User.ID
	}

	exeamLog := &model.ExeamLog{}
	found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
		Db:          db,
		CollectName: repo.CollectionExeamLog,
		Query:       repo.Map{"uid": uid},
		Sort:        bson.M{"score": -1},
	}, exeamLog)
	if err != nil {
		return nil, err
	}
	if !found {
		return 0, nil
	}
	return exeamLog.Score, nil
}

// 个人: 已学习模块数
// 统计各个模块的学习总时长,根据总时长时间判断是否已学习
// 只需要返回统计各个模块的时长汇总,cid相同的为同一个模块
func StatisticsLearnedModules(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	// 如果没有uid参数,则查询当前用户的
	uid := c.Query("uid")
	if len(uid) == 0 {
		uid = apictx.User.ID
	}

	colls := apictx.CreateRepoCtx().Client.GetDbCollection(db, repo.CollectionLearnLog)
	pipeline := mongo.Pipeline{
		{
			{Key: "$match", Value: bson.D{
				{Key: "uid", Value: uid},
			}},
		},
		{
			{Key: "$group", Value: bson.D{
				{Key: "_id", Value: "$cid"},
				{Key: "totalLearnTime", Value: bson.D{{Key: "$sum", Value: "$learnTime"}}},
			}},
		},
	}

	cursor, err := colls.Aggregate(apictx.CreateRepoCtx().Ctx, pipeline)
	if err != nil {
		return nil, err
	}

	var results []bson.M
	if err = cursor.All(apictx.CreateRepoCtx().Ctx, &results); err != nil {
		return nil, err
	}

	return results, nil
}

// 个人: 统计用户本年每月考核正确和错误数
func StatisticsExeamTFRate(c *gin.Context, apictx *ApiSession) (interface{}, error) {
	db := c.Param("scope")
	if len(db) == 0 {
		return nil, errors.New("scope不能为空")
	}
	// 如果没有uid参数,则查询当前用户的
	uid := c.Query("uid")
	if len(uid) == 0 {
		uid = apictx.User.ID
	}
	_year := c.Query("year")
	year := 2024
	if len(_year) == 0 {
		year = time.Now().Year()
	} else {
		year_, err := strconv.Atoi(_year)
		if err != nil {
			return nil, errors.New("year参数错误")
		}
		year = year_
	}

	fmt.Println(year)
	colls := apictx.CreateRepoCtx().Client.GetDbCollection(db, repo.CollectionExeamLog)
	chinaTimeZone := time.FixedZone("CST", 8*60*60) // 中国时区
	fmt.Println(uid)

	pipeline := mongo.Pipeline{
		// 筛选出特定时间范围的记录
		{
			{Key: "$match", Value: bson.D{
				{Key: "createTime", Value: bson.D{
					{Key: "$gte", Value: time.Date(year, time.January, 1, 0, 0, 0, 0, chinaTimeZone)},
					{Key: "$lt", Value: time.Date(year+1, time.January, 1, 0, 0, 0, 0, chinaTimeZone)},
				}},
			}},
		},
		// 将 createTime 字段分解为年和月
		{
			{Key: "$addFields", Value: bson.D{
				// {"year", bson.D{{"$year", bson.D{{"$add", []interface{}{"$createTime", 8 * 60 * 60 * 1000}}}}}},
				{Key: "month", Value: bson.D{{Key: "$month", Value: bson.D{{Key: "$add", Value: []interface{}{"$createTime", 8 * 60 * 60 * 1000}}}}}},
			}},
		},
		// 按年和月分组，并计算每个月的正确和错误数量
		{
			{Key: "$group", Value: bson.D{
				{Key: "_id", Value: "$month"},
				{Key: "correct", Value: bson.D{{Key: "$sum", Value: "$correct"}}},
				{Key: "error", Value: bson.D{{Key: "$sum", Value: "$error"}}},
			}},
		},
		// 排序结果
		{
			{Key: "$sort", Value: bson.D{{Key: "_id", Value: 1}}},
		},
	}

	cursor, err := colls.Aggregate(context.TODO(), pipeline)
	if err != nil {
		return nil, err
	}

	var results []bson.M
	if err = cursor.All(apictx.CreateRepoCtx().Ctx, &results); err != nil {
		return nil, err
	}

	return results, nil

}
