package rbac

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"hyapp-admin-server/internal/middleware"
	"hyapp-admin-server/internal/modules/shared"
	"hyapp-admin-server/internal/repository"
	"hyapp-admin-server/internal/response"
)

type Handler struct {
	service *RBACService
	audit   shared.OperationLogger
}

func New(store *repository.Store, audit shared.OperationLogger) *Handler {
	return &Handler{service: NewService(store), audit: audit}
}

func (h *Handler) ListPermissions(c *gin.Context) {
	permissions, err := h.service.ListPermissions()
	if err != nil {
		response.ServerError(c, "获取权限失败")
		return
	}
	response.OK(c, permissions)
}

func (h *Handler) CreatePermission(c *gin.Context) {
	var req permissionRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "权限名称、编码和类型不能为空")
		return
	}

	permission, err := h.service.CreatePermission(PermissionInput{Name: req.Name, Code: req.Code, Kind: req.Kind, Description: req.Description})
	if err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "create-permission", "admin_permissions", "success", permission.Code)
	response.Created(c, *permission)
}

func (h *Handler) UpdatePermission(c *gin.Context) {
	id, ok := shared.ParseID(c, "id")
	if !ok {
		return
	}
	var req permissionRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "权限名称、编码和类型不能为空")
		return
	}

	permission, err := h.service.UpdatePermission(id, PermissionInput{Name: req.Name, Code: req.Code, Kind: req.Kind, Description: req.Description})
	if err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "update-permission", "admin_permissions", "success", permission.Code)
	response.OK(c, permission)
}

func (h *Handler) DeletePermission(c *gin.Context) {
	id, ok := shared.ParseID(c, "id")
	if !ok {
		return
	}
	if err := h.service.DeletePermission(id); err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "delete-permission", "admin_permissions", "success", fmt.Sprintf("permission_id=%d", id))
	response.OK(c, gin.H{"deleted": true})
}

func (h *Handler) SyncPermissions(c *gin.Context) {
	// 同步只写入系统内置权限，不删除人工新增权限，避免新功能上线时破坏现场配置。
	if err := h.service.SyncPermissions(); err != nil {
		response.ServerError(c, "同步权限失败")
		return
	}
	shared.OperationLog(c, h.audit, "sync-permissions", "admin_permissions", "success", "default permissions")
	response.OK(c, gin.H{"synced": true})
}

func (h *Handler) ListRoles(c *gin.Context) {
	roles, err := h.service.ListRoles()
	if err != nil {
		response.ServerError(c, "获取角色失败")
		return
	}
	response.OK(c, roles)
}

func (h *Handler) CreateRole(c *gin.Context) {
	var req roleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "角色名称和编码不能为空")
		return
	}
	if len(req.PermissionIDs) > 0 && !middleware.HasAnyPermission(c, "role:permission", "role:manage") {
		// 创建角色和授予权限是两个风险等级，直接调用 API 时也必须阻断越权授权。
		response.Forbidden(c, "没有角色授权权限")
		return
	}

	role, err := h.service.CreateRole(RoleInput{Name: req.Name, Code: req.Code, Description: req.Description, PermissionIDs: req.PermissionIDs})
	if err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "create-role", "admin_roles", "success", role.Name)
	response.Created(c, *role)
}

func (h *Handler) UpdateRole(c *gin.Context) {
	id, ok := shared.ParseID(c, "id")
	if !ok {
		return
	}
	var req roleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "角色名称和编码不能为空")
		return
	}
	// 角色基础信息和角色授权分开保存，避免只有编辑权限的操作者顺带修改权限集合。
	role, err := h.service.UpdateRole(id, RoleInput{Name: req.Name, Code: req.Code, Description: req.Description})
	if err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "update-role", "admin_roles", "success", role.Name)
	response.OK(c, role)
}

func (h *Handler) DeleteRole(c *gin.Context) {
	id, ok := shared.ParseID(c, "id")
	if !ok {
		return
	}
	if err := h.service.DeleteRole(id); err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "delete-role", "admin_roles", "success", fmt.Sprintf("role_id=%d", id))
	response.OK(c, gin.H{"deleted": true})
}

func (h *Handler) ReplaceRolePermissions(c *gin.Context) {
	id, ok := shared.ParseID(c, "id")
	if !ok {
		return
	}
	var req rolePermissionRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "权限参数不正确")
		return
	}
	if err := h.service.ReplaceRolePermissions(id, req.PermissionIDs); err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "replace-role-permissions", "admin_role_permissions", "success", fmt.Sprintf("role_id=%d", id))
	response.OK(c, gin.H{"updated": true})
}

func (h *Handler) GetRoleDataScopes(c *gin.Context) {
	id, ok := shared.ParseID(c, "id")
	if !ok {
		return
	}
	scopes, err := h.service.ListRoleDataScopes(id)
	if err != nil {
		response.ServerError(c, "获取数据权限失败")
		return
	}
	response.OK(c, gin.H{"items": scopes})
}

func (h *Handler) ReplaceRoleDataScopes(c *gin.Context) {
	id, ok := shared.ParseID(c, "id")
	if !ok {
		return
	}
	var req dataScopeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "数据权限参数不正确")
		return
	}
	scopes := make([]DataScopeItem, 0, len(req.Scopes))
	for _, item := range req.Scopes {
		scopes = append(scopes, DataScopeItem{ScopeType: item.ScopeType, ScopeValue: item.ScopeValue})
	}
	if err := h.service.ReplaceRoleDataScopes(id, DataScopeInput{Scopes: scopes}); err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "replace-role-data-scopes", "admin_data_scopes", "success", fmt.Sprintf("role_id=%d scopes=%d", id, len(scopes)))
	response.OK(c, gin.H{"updated": true})
}
