package handlers

import (
	"net/http"
	"strings"

	"stock-user-system/internal/config"
	"stock-user-system/internal/middleware"
	"stock-user-system/internal/models"

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

type AdminHandler struct {
	DB  *gorm.DB
	CFG *config.Config
}

func allowedRolesForCreation(actor models.RoleName) []models.RoleName {
	switch actor {
	case models.RoleSystemAdmin:
		return []models.RoleName{models.RoleAdmin, models.RoleUser}
	case models.RoleAdmin:
		return []models.RoleName{models.RoleUser}
	default:
		return nil
	}
}

func containsRole(roles []models.RoleName, target models.RoleName) bool {
	for _, r := range roles {
		if r == target {
			return true
		}
	}
	return false
}

func (h *AdminHandler) ListUsers(c *gin.Context) {
	var users []models.User
	if err := h.DB.Preload("Role").Order("created_at DESC").Find(&users).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"})
		return
	}

	result := make([]models.PublicUserInfo, 0, len(users))
	for _, u := range users {
		result = append(result, u.ToPublicInfo())
	}
	c.JSON(http.StatusOK, result)
}

func (h *AdminHandler) CreateUser(c *gin.Context) {
	current, _ := middleware.GetCurrentUser(c)

	var req struct {
		Username string  `json:"username" binding:"required"`
		Email    *string `json:"email"`
		Password string  `json:"password" binding:"required"`
		Role     string  `json:"role"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "请求参数错误"})
		return
	}

	targetRole := models.RoleUser
	if req.Role != "" {
		parsed, err := models.ParseRoleName(req.Role)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "无效的角色"})
			return
		}
		targetRole = parsed
	}

	if !containsRole(allowedRolesForCreation(current.Role), targetRole) {
		c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "权限不足"})
		return
	}

	if err := validateUsername(req.Username); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": err.Error()})
		return
	}
	if len(req.Password) < 6 {
		c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "密码长度至少 6 位"})
		return
	}

	var role models.Role
	if err := h.DB.Where("name = ?", targetRole.String()).First(&role).Error; err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "角色不存在"})
		return
	}

	hash, err := hashPassword(req.Password)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"})
		return
	}

	username := strings.ToLower(strings.TrimSpace(req.Username))
	var email *string
	if req.Email != nil && *req.Email != "" {
		e := strings.ToLower(strings.TrimSpace(*req.Email))
		email = &e
	}

	user := models.User{
		Username:     username,
		Email:        email,
		PasswordHash: hash,
		RoleID:       role.ID,
		Status:       "active",
	}

	if err := h.DB.Create(&user).Error; err != nil {
		if strings.Contains(err.Error(), "duplicate key") {
			c.JSON(http.StatusConflict, gin.H{"success": false, "error": "用户名或邮箱已存在"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"})
		return
	}

	h.DB.Preload("Role").First(&user, "id = ?", user.ID)
	c.JSON(http.StatusOK, user.ToPublicInfo())
}

func (h *AdminHandler) UpdateUser(c *gin.Context) {
	current, _ := middleware.GetCurrentUser(c)
	userID := c.Param("id")

	var req struct {
		Email  *string `json:"email"`
		Role   string  `json:"role"`
		Status string  `json:"status"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "请求参数错误"})
		return
	}

	var target models.User
	if err := h.DB.Preload("Role").Where("id = ?", userID).First(&target).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"success": false, "error": "not found"})
		return
	}

	if !current.Role.CanManage(target.Role.NameEnum()) && current.ID != userID {
		c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "权限不足"})
		return
	}

	updates := map[string]interface{}{}

	if req.Email != nil && *req.Email != "" {
		updates["email"] = strings.ToLower(strings.TrimSpace(*req.Email))
	}

	if req.Status != "" {
		if target.Role.NameEnum() == models.RoleSystemAdmin && req.Status != "active" {
			c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "不能禁用系统管理员账号"})
			return
		}
		updates["status"] = req.Status
	}

	if req.Role != "" {
		newRole, err := models.ParseRoleName(req.Role)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "无效的角色"})
			return
		}
		if target.Role.NameEnum() == models.RoleSystemAdmin && newRole != models.RoleSystemAdmin {
			c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "不能修改系统管理员账号的角色"})
			return
		}
		if !containsRole(allowedRolesForCreation(current.Role), newRole) || !current.Role.CanManage(newRole) {
			c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "权限不足"})
			return
		}
		var role models.Role
		if err := h.DB.Where("name = ?", newRole.String()).First(&role).Error; err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "角色不存在"})
			return
		}
		updates["role_id"] = role.ID
	}

	if err := h.DB.Model(&target).Updates(updates).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"})
		return
	}

	h.DB.Preload("Role").First(&target, "id = ?", userID)
	c.JSON(http.StatusOK, target.ToPublicInfo())
}

func (h *AdminHandler) DeleteUser(c *gin.Context) {
	current, _ := middleware.GetCurrentUser(c)
	userID := c.Param("id")

	if current.ID == userID {
		c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "不能删除自己"})
		return
	}

	var target models.User
	if err := h.DB.Preload("Role").Where("id = ?", userID).First(&target).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"success": false, "error": "not found"})
		return
	}

	if !current.Role.CanManage(target.Role.NameEnum()) {
		c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "权限不足"})
		return
	}

	if target.Role.NameEnum() == models.RoleSystemAdmin {
		c.JSON(http.StatusForbidden, gin.H{"success": false, "error": "不能删除系统管理员账号"})
		return
	}

	if err := h.DB.Delete(&target).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "用户已删除"})
}

func (h *AdminHandler) ListRoles(c *gin.Context) {
	var roles []models.Role
	if err := h.DB.Order("id").Find(&roles).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "internal server error"})
		return
	}
	c.JSON(http.StatusOK, roles)
}
