package middleware

import (
	"errors"
	"os"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"github.com/niangaodev/art-code/repositories"
	"github.com/niangaodev/art-code/utils"
)

// JWT密钥
var jwtSecret = []byte(getJWTSecret())

// getJWTSecret 获取JWT密钥，优先从环境变量获取，否则使用默认值
func getJWTSecret() string {
	secret := os.Getenv("JWT_SECRET")
	if secret == "" {
		return "your-secret-key" // 开发环境默认值，生产环境必须通过环境变量设置
	}
	return secret
}

// Claims JWT声明结构
type Claims struct {
	UserID   uint   `json:"userId"`
	Username string `json:"username"`
	Role     string `json:"role"`
	RoleID   uint   `json:"roleId"`
	jwt.RegisteredClaims
}

// GenerateToken 生成JWT令牌
func GenerateToken(userID uint, username, role string) (string, int64, error) {
	// 设置令牌过期时间为7天
	expireTime := time.Now().Add(7 * 24 * time.Hour)
	expireUnix := expireTime.Unix()

	// 获取用户的RoleID
	var roleID uint
	userRole, err := repositories.GetRoleByName(role)
	if err == nil && userRole != nil {
		roleID = userRole.ID
	}

	// 创建声明
	claims := Claims{
		UserID:   userID,
		Username: username,
		Role:     role,
		RoleID:   roleID,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(expireTime),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			Subject:   "admin-token",
		},
	}

	// 创建令牌
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// 签名令牌
	tokenString, err := token.SignedString(jwtSecret)
	if err != nil {
		return "", 0, err
	}

	return tokenString, expireUnix, nil
}

// ParseToken 解析JWT令牌
func ParseToken(tokenString string) (*Claims, error) {
	// 解析令牌
	token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return jwtSecret, nil
	})

	if err != nil {
		return nil, err
	}

	// 验证令牌
	if claims, ok := token.Claims.(*Claims); ok && token.Valid {
		return claims, nil
	}

	return nil, errors.New("invalid token")
}

// AuthMiddleware JWT认证中间件
func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从请求头中获取令牌
		authHeader := c.GetHeader("Authorization")
		if authHeader == "" {
			utils.Error(c, 401, "登录已过期，请重新登录")
			c.Abort()
			return
		}

		// 检查令牌格式
		parts := strings.SplitN(authHeader, " ", 2)
		if !(len(parts) == 2 && parts[0] == "Bearer") {
			utils.Error(c, 401, "登录已过期，请重新登录")
			c.Abort()
			return
		}

		// 解析令牌
		claims, err := ParseToken(parts[1])
		if err != nil {
			utils.Error(c, 401, "登录已过期，请重新登录")
			c.Abort()
			return
		}

		// 将用户信息存储到上下文
		c.Set("userID", claims.UserID)
		c.Set("username", claims.Username)
		c.Set("role", claims.Role)
		c.Set("roleID", claims.RoleID)

		c.Next()
	}
}

// RoleMiddleware 角色验证中间件 (Legacy support)
func RoleMiddleware(roles ...string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从上下文中获取用户角色
		role, exists := c.Get("role")
		if !exists {
			utils.Error(c, 401, "未授权，请重新登录")
			c.Abort()
			return
		}

		// 检查用户角色是否在允许列表中
		allowed := false
		for _, r := range roles {
			if role == r {
				allowed = true
				break
			}
		}

		if !allowed {
			utils.Error(c, 403, "权限不足")
			c.Abort()
			return
		}

		c.Next()
	}
}

// PermissionMiddleware 权限验证中间件
func PermissionMiddleware(resource, action string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取用户RoleID
		roleIDInterface, exists := c.Get("roleID")
		if !exists {
			// 尝试从role name获取
			roleName, exists := c.Get("role")
			if !exists {
				utils.Error(c, 401, "未授权，请重新登录")
				c.Abort()
				return
			}
			role, err := repositories.GetRoleByName(roleName.(string))
			if err != nil || role == nil {
				utils.Error(c, 403, "角色不存在")
				c.Abort()
				return
			}
			roleIDInterface = role.ID
		}

		roleID := roleIDInterface.(uint)

		// 获取该角色的所有权限
		permissions, err := repositories.GetPermissionsByRoleID(roleID)
		if err != nil {
			utils.Error(c, 500, "权限校验失败")
			c.Abort()
			return
		}

		// 检查是否有匹配的权限
		allowed := false
		for _, p := range permissions {
			if p.Resource == resource && p.Action == action {
				allowed = true
				break
			}
		}

		if !allowed {
			utils.Error(c, 403, "权限不足")
			c.Abort()
			return
		}

		c.Next()
	}
}
