package handlers

import (
	"fmt"
	"net/http"

	"software-download-center/database"
	"software-download-center/models"
	"software-download-center/utils"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// RegisterRequest 注册请求
type RegisterRequest struct {
	Username string `json:"username" binding:"required,min=3,max=50"`
	Email    string `json:"email" binding:"required,email"`
	Password string `json:"password" binding:"required,min=8"`
}

// LoginRequest 登录请求
type LoginRequest struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

// Register 用户注册
func Register(c *gin.Context) {
	var req RegisterRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数错误: " + err.Error(),
		})
		return
	}

	// 验证密码强度
	if err := utils.ValidatePasswordStrength(req.Password); err != nil {
		AddLog("WARN", fmt.Sprintf("注册失败（密码强度不足）: 用户名=%s, IP=%s", req.Username, c.ClientIP()))
		c.JSON(http.StatusBadRequest, gin.H{
			"error": err.Error(),
		})
		return
	}

	// 检查用户名是否已存在
	var existingUser models.User
	if err := database.DB.Where("username = ?", req.Username).First(&existingUser).Error; err == nil {
		AddLog("WARN", fmt.Sprintf("注册失败（用户名已存在）: 用户名=%s, IP=%s", req.Username, c.ClientIP()))
		c.JSON(http.StatusConflict, gin.H{
			"error": "用户名已存在",
		})
		return
	}

	// 检查邮箱是否已存在
	if err := database.DB.Where("email = ?", req.Email).First(&existingUser).Error; err == nil {
		AddLog("WARN", fmt.Sprintf("注册失败（邮箱已被注册）: 邮箱=%s, IP=%s", req.Email, c.ClientIP()))
		c.JSON(http.StatusConflict, gin.H{
			"error": "邮箱已被注册",
		})
		return
	}

	// 检查是否是第一个用户（自动成为管理员）
	var userCount int64
	database.DB.Model(&models.User{}).Count(&userCount)
	isAdmin := userCount == 0

	// 加密密码
	hashedPassword, err := utils.HashPassword(req.Password)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "密码加密失败",
		})
		return
	}

	// 创建用户
	user := models.User{
		Username: req.Username,
		Email:    req.Email,
		Password: hashedPassword,
		IsAdmin:  isAdmin,
		IsActive: true,
	}

	if err := database.DB.Create(&user).Error; err != nil {
		AddLog("ERROR", fmt.Sprintf("创建用户数据库错误: 用户名=%s - %s, IP=%s", req.Username, err.Error(), c.ClientIP()))
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "创建用户失败",
		})
		return
	}

	AddLog("INFO", fmt.Sprintf("用户注册成功: 用户名=%s, 邮箱=%s, 管理员=%v, IP=%s", user.Username, user.Email, user.IsAdmin, c.ClientIP()))

	// 生成 token
	token, err := utils.GenerateToken(user.ID, user.Username, user.IsAdmin)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "生成 token 失败",
		})
		return
	}

	// 设置 cookie
	c.SetCookie("token", token, 24*3600, "/", "", false, true)

	c.JSON(http.StatusOK, gin.H{
		"message":  "注册成功",
		"token":    token,
		"user": gin.H{
			"id":       user.ID,
			"username": user.Username,
			"email":    user.Email,
			"is_admin": user.IsAdmin,
		},
	})
}

// Login 用户登录
func Login(c *gin.Context) {
	var req LoginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": "请求参数错误",
		})
		return
	}

	// 检查数据库是否已初始化
	if !database.IsDBInitialized() {
		// 使用默认管理员账号
		if req.Username == "admin" && req.Password == "admin123456" {
			// 生成临时 token（用于安装页面）
			token, err := utils.GenerateToken(0, "admin", true)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{
					"error": "生成 token 失败",
				})
				return
			}

			AddLog("INFO", fmt.Sprintf("默认管理员登录成功: 用户名=%s, IP=%s", req.Username, c.ClientIP()))
			c.SetCookie("token", token, 24*3600, "/", "", false, true)
			c.JSON(http.StatusOK, gin.H{
				"message": "登录成功，请配置数据库",
				"token":   token,
				"user": gin.H{
					"id":       0,
					"username": "admin",
					"is_admin": true,
					"is_setup": false, // 标记需要安装
				},
			})
			return
		}

		c.JSON(http.StatusUnauthorized, gin.H{
			"error": "数据库未初始化，请使用默认管理员账号登录（admin/admin123456）",
		})
		return
	}

	// 查找用户
	var user models.User
	if err := database.DB.Where("username = ?", req.Username).First(&user).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			AddLog("WARN", fmt.Sprintf("登录失败（用户不存在）: 用户名=%s, IP=%s", req.Username, c.ClientIP()))
			c.JSON(http.StatusUnauthorized, gin.H{
				"error": "用户名或密码错误",
			})
			return
		}
		AddLog("ERROR", fmt.Sprintf("查询用户失败: 用户名=%s - %s, IP=%s", req.Username, err.Error(), c.ClientIP()))
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "查询用户失败",
		})
		return
	}

	// 检查用户是否激活
	if !user.IsActive {
		AddLog("WARN", fmt.Sprintf("登录失败（账户已禁用）: 用户名=%s, IP=%s", req.Username, c.ClientIP()))
		c.JSON(http.StatusForbidden, gin.H{
			"error": "账户已被禁用",
		})
		return
	}

	// 验证密码
	if !utils.CheckPassword(req.Password, user.Password) {
		AddLog("WARN", fmt.Sprintf("登录失败（密码错误）: 用户名=%s, IP=%s", req.Username, c.ClientIP()))
		c.JSON(http.StatusUnauthorized, gin.H{
			"error": "用户名或密码错误",
		})
		return
	}

	AddLog("INFO", fmt.Sprintf("用户登录成功: 用户名=%s, 管理员=%v, IP=%s", user.Username, user.IsAdmin, c.ClientIP()))

	// 生成 token
	token, err := utils.GenerateToken(user.ID, user.Username, user.IsAdmin)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error": "生成 token 失败",
		})
		return
	}

	// 设置 cookie
	c.SetCookie("token", token, 24*3600, "/", "", false, true)

	c.JSON(http.StatusOK, gin.H{
		"message": "登录成功",
		"token":   token,
		"user": gin.H{
			"id":       user.ID,
			"username": user.Username,
			"email":    user.Email,
			"is_admin": user.IsAdmin,
		},
	})
}

// Logout 用户登出
func Logout(c *gin.Context) {
	c.SetCookie("token", "", -1, "/", "", false, true)
	c.JSON(http.StatusOK, gin.H{
		"message": "登出成功",
	})
}

// GetCurrentUser 获取当前用户信息
func GetCurrentUser(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"error": "未授权",
		})
		return
	}

	var user models.User
	if err := database.DB.First(&user, userID).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"error": "用户不存在",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"user": gin.H{
			"id":       user.ID,
			"username": user.Username,
			"email":    user.Email,
			"is_admin": user.IsAdmin,
			"is_active": user.IsActive,
		},
	})
}
