package main

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"golang.org/x/crypto/bcrypt"
)

var jwtSecret = []byte("frpc-console-secret-key-2024")

type Claims struct {
	Username string `json:"username"`
	jwt.RegisteredClaims
}

func GenerateJWT(username string) (string, error) {
	claims := Claims{
		Username: username,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(7 * 24 * time.Hour)),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(jwtSecret)
}

func ParseJWT(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")
}

// 密码复杂度验证：至少3个大写 + 8个数字 + 1个特殊字符
func ValidatePassword(pwd string) bool {
	var upper, digit, special int
	for _, ch := range pwd {
		if ch >= 'A' && ch <= 'Z' {
			upper++
		}
		if ch >= '0' && ch <= '9' {
			digit++
		}
		if strings.ContainsAny(string(ch), "!@#$%^&*()_+-=[]{}|;:,.<>?") {
			special++
		}
	}
	return upper >= 3 && digit >= 8 && special >= 1 && len(pwd) >= 12
}

// 首次启动强制设置管理员账户
func InitAdminUser() {
	count, err := CountUsers()
	if err != nil {
		log.Fatal("❌ 检查用户表失败:", err)
	}

	if count > 0 {
		log.Println("✅ 已存在管理员账户，跳过初始化")
		return
	}

	log.Println("⚠️  首次启动，请设置管理员账户")
	log.Print("用户名: ")
	var username string
	fmt.Scanln(&username)

	if username == "" {
		username = "admin"
	}

	for {
		log.Print("密码 (至少3个大写+8个数字+1个特殊字符): ")
		var password string
		fmt.Scanln(&password)

		if ValidatePassword(password) {
			hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
			if err != nil {
				log.Println("❌ 密码加密失败:", err)
				continue
			}
			err = CreateUser(username, string(hash))
			if err != nil {
				log.Println("❌ 创建用户失败:", err)
				continue
			}
			log.Println("✅ 管理员账户创建成功！")
			break
		} else {
			log.Println("❌ 密码不符合复杂度要求，请重新输入")
			log.Println("   要求: 至少3个大写字母 + 8个数字 + 1个特殊字符")
		}
	}
}

// JWT 认证中间件
func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		authHeader := c.GetHeader("Authorization")
		if authHeader == "" {
			c.JSON(http.StatusUnauthorized, gin.H{"code": 1, "msg": "未提供认证令牌"})
			c.Abort()
			return
		}
		// 格式 "Bearer <token>"
		parts := strings.SplitN(authHeader, " ", 2)
		if len(parts) != 2 || parts[0] != "Bearer" {
			c.JSON(http.StatusUnauthorized, gin.H{"code": 1, "msg": "认证令牌格式错误"})
			c.Abort()
			return
		}
		tokenString := parts[1]
		claims, err := ParseJWT(tokenString)
		if err != nil {
			c.JSON(http.StatusUnauthorized, gin.H{"code": 1, "msg": "无效的认证令牌"})
			c.Abort()
			return
		}
		// 将用户名存入上下文，方便后续使用
		c.Set("username", claims.Username)
		c.Next()
	}
}
