package handlers

import (
	"context"
	"net/http"
	"strconv"
	"time"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo/options"

	"yh_web/server/config"
	"yh_web/server/models"

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

const customRoleIDStart = 1000 // 自定义角色 role_id 从此值起

// GetRolePermissionsList 返回所有角色及其权限（含预定义与自定义）
func GetRolePermissionsList(c *gin.Context) {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	coll := config.GetDB(config.DBName).Collection("role_permissions")
	cursor, err := coll.Find(ctx, bson.M{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer cursor.Close(ctx)

	var docs []models.RolePermissionsDoc
	if err = cursor.All(ctx, &docs); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	permMap := make(map[int][]string)
	nameMap := make(map[int]string)
	for _, d := range docs {
		permMap[d.RoleID] = d.Permissions
		if d.RoleName != "" {
			nameMap[d.RoleID] = d.RoleName
		}
	}
	allKeys := allPermissionKeys()
	// 预定义角色固定在前（9527, 0, 1），再按 role_id 排自定义
	predef := []int{models.RoleIDSuperAdmin, models.RoleIDSuperUser, models.RoleIDUser}
	seen := make(map[int]bool)
	list := make([]gin.H, 0)
	for _, rid := range predef {
		seen[rid] = true
		perms := permMap[rid]
		if perms == nil {
			perms = []string{}
		}
		if rid == models.RoleIDSuperAdmin {
			perms = allKeys
		}
		name := nameMap[rid]
		if name == "" {
			name = models.DefaultRoleNames[rid]
		}
		list = append(list, gin.H{
			"role_id":     rid,
			"role_name":   name,
			"permissions": perms,
			"is_custom":   false,
		})
	}
	for _, d := range docs {
		if seen[d.RoleID] {
			continue
		}
		seen[d.RoleID] = true
		name := d.RoleName
		if name == "" {
			name = "角色" + strconv.Itoa(d.RoleID)
		}
		perms := d.Permissions
		if perms == nil {
			perms = []string{}
		}
		list = append(list, gin.H{
			"role_id":     d.RoleID,
			"role_name":   name,
			"permissions": perms,
			"is_custom":   true,
		})
	}
	c.JSON(http.StatusOK, gin.H{
		"list":            list,
		"all_permissions": models.AllPermissions,
	})
}

// UpdateRolePermissions 更新指定角色的权限
func UpdateRolePermissions(c *gin.Context) {
	roleIDStr := c.Param("role_id")
	roleID, err := strconv.Atoi(roleIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 role_id"})
		return
	}
	if roleID == models.RoleIDSuperAdmin {
		c.JSON(http.StatusBadRequest, gin.H{"error": "超级管理员权限不可修改"})
		return
	}

	var input struct {
		RoleName    string   `json:"role_name"`
		Permissions []string `json:"permissions"`
	}
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	coll := config.GetDB(config.DBName).Collection("role_permissions")
	filter := bson.M{"role_id": roleID}
	set := bson.M{"role_id": roleID, "permissions": input.Permissions}
	if input.RoleName != "" && roleID >= customRoleIDStart {
		set["role_name"] = input.RoleName
	}
	update := bson.M{"$set": set}
	opts := options.UpdateOne().SetUpsert(true)
	_, err = coll.UpdateOne(ctx, filter, update, opts)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "保存成功", "role_id": roleID, "permissions": input.Permissions})
}

// CreateRoleInput 创建角色
type CreateRoleInput struct {
	RoleName    string   `json:"role_name" binding:"required"`
	Permissions []string `json:"permissions"`
}

// CreateRole 创建自定义角色
func CreateRole(c *gin.Context) {
	var input CreateRoleInput
	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请填写角色名称"})
		return
	}
	if input.Permissions == nil {
		input.Permissions = []string{}
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	coll := config.GetDB(config.DBName).Collection("role_permissions")
	cursor, _ := coll.Find(ctx, bson.M{"role_id": bson.M{"$gte": customRoleIDStart}}, options.Find().SetSort(bson.D{{Key: "role_id", Value: -1}}).SetLimit(1))
	var docs []models.RolePermissionsDoc
	_ = cursor.All(ctx, &docs)
	cursor.Close(ctx)
	nextID := customRoleIDStart
	for _, d := range docs {
		if d.RoleID >= customRoleIDStart {
			nextID = d.RoleID + 1
			break
		}
	}

	doc := models.RolePermissionsDoc{
		RoleID:      nextID,
		RoleName:    input.RoleName,
		Permissions: input.Permissions,
	}
	_, err := coll.InsertOne(ctx, bson.M{"role_id": doc.RoleID, "role_name": doc.RoleName, "permissions": doc.Permissions})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "创建成功", "role_id": doc.RoleID, "role_name": doc.RoleName, "permissions": doc.Permissions})
}

// DeleteRole 删除自定义角色（仅 role_id >= customRoleIDStart）
func DeleteRole(c *gin.Context) {
	roleIDStr := c.Param("role_id")
	roleID, err := strconv.Atoi(roleIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 role_id"})
		return
	}
	if roleID < customRoleIDStart {
		c.JSON(http.StatusBadRequest, gin.H{"error": "预定义角色不可删除"})
		return
	}
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	coll := config.GetDB(config.DBName).Collection("role_permissions")
	_, err = coll.DeleteOne(ctx, bson.M{"role_id": roleID})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
}
