package router

import (
	"context"
	"errors"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis/v8"
	mhayaTime "github.com/mhaya/extend/time"
	cfacade "github.com/mhaya/facade"
	"github.com/mhaya/game/game_cluster/internal/code"
	"github.com/mhaya/game/game_cluster/internal/constant"
	"github.com/mhaya/game/game_cluster/internal/mdb"
	"github.com/mhaya/game/game_cluster/internal/mdb/models"
	"github.com/mhaya/game/game_cluster/nodes/adminapi/common"
	"github.com/mhaya/game/game_cluster/nodes/adminapi/model"
	"github.com/mhaya/game/game_cluster/nodes/adminapi/service"
	mhayaLogger "github.com/mhaya/logger"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
)

func Auth(settingObj cfacade.ProfileJSON) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 请求开始时间
		startTime := mhayaTime.Now().UnixMilli()

		tokenString := c.GetHeader("Token")
		if tokenString == "" {
			common.PackUnauthorizedResult(c, code.UnauthorizedError, "token is empty")
			return
		}

		roleId, err := mdb.RDB.Get(context.Background(), tokenString).Result()
		if err != nil && err != redis.Nil {
			mhayaLogger.Warnf("Auth Get error: %s", err.Error())
			common.PackUnauthorizedResult(c, code.InternalError, "token is empty")
			return
		}
		if roleId == "" {
			common.PackUnauthorizedResult(c, code.UnauthorizedError, "token is invalid")
			return
		}

		if roleId != constant.AdminAccess {
			urlAccess, err := mdb.RDB.HGet(context.Background(), common.GetTokenKey(tokenString), c.Request.URL.Path).Result()
			if err != nil {
				mhayaLogger.Warnf("Auth HGet s error: %s", err.Error())
				common.PackUnauthorizedResult(c, code.InternalError, "")
				return
			}

			// 检查url权限
			if urlAccess == "" {
				common.PackUnauthorizedResult(c, code.UnauthorizedError, "token is no auth")
				return
			}

			// 非管理员需要进行ip校验
			openIpWhitelist := settingObj.Get("open_ip_whitelist").ToBool()
			if openIpWhitelist {
				err = checkIPWhitelist(c)
				if err != nil {
					mhayaLogger.Warnf("Auth checkIPWhitelist error: %s", err.Error())
					common.PackForbiddenResult(c, code.ForbiddenError, "ip is no auth")
					return
				}
			}
		}

		adminAccess, err := mdb.RDB.HGet(context.Background(), common.GetTokenKey(tokenString), constant.AdminAccess).Result()
		if err != nil {
			mhayaLogger.Warnf("Auth HGet ss error: %s", err.Error())
			common.PackUnauthorizedResult(c, code.InternalError, "")
			return
		}

		// 检查管理员权限
		if adminAccess == "" {
			common.PackUnauthorizedResult(c, code.UnauthorizedError, "token is no auth")
			return
		}

		c.Next()

		userName, err := mdb.RDB.Get(context.Background(), common.GetUserNameKey(tokenString)).Result()
		if err == nil {
			service.NewSynthesis().InsertRecord(model.UserOperationLog{
				Username:     userName,
				RoleId:       roleId,
				Path:         c.Request.URL.Path,
				Method:       c.Request.Method,
				StatusCode:   c.Writer.Status(),
				Dur:          mhayaTime.Now().UnixMilli() - startTime,
				ClientIP:     c.ClientIP(),
				ErrorMessage: c.Errors.ByType(gin.ErrorTypePrivate).String(),
			})
		}
	}
}

// checkIP
func checkIPWhitelist(c *gin.Context) error {
	// 获取请求的ip
	ip := c.ClientIP()
	var whitelistModel *models.Whitelist
	collection := mdb.MDB.Collection(whitelistModel.TableName())

	// 设置超时时间
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel() // 确保在函数退出时取消上下文

	// 示例：查询 IP 是否在白名单中
	err := collection.FindOne(ctx, bson.M{"ip": ip}).Decode(&whitelistModel)
	if err != nil && err != mongo.ErrNoDocuments {
		return err
	}

	// 根据查询结果决定是否允许访问
	if whitelistModel == nil {
		return errors.New("IP not in whitelist") // 拒绝访问
	}

	return nil // 允许访问
}
