package menu

import (
	"fmt"

	"hyapp-admin-server/internal/modules/shared"
	"hyapp-admin-server/internal/repository"
	"hyapp-admin-server/internal/response"

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

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

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

func (h *Handler) NavigationMenus(c *gin.Context) {
	menus, err := h.service.NavigationMenus(shared.ActorFromContext(c))
	if err != nil {
		response.ServerError(c, "获取菜单失败")
		return
	}

	response.OK(c, pruneEmptyMenuGroups(buildMenuTree(menus)))
}

func (h *Handler) ListSystemMenus(c *gin.Context) {
	// navigation/menus 是当前用户菜单；system/menus 是维护页全量菜单，二者权限边界不同。
	menus, err := h.service.ListSystemMenus()
	if err != nil {
		response.ServerError(c, "获取菜单失败")
		return
	}
	response.OK(c, buildMenuTree(menus))
}

func (h *Handler) CreateMenu(c *gin.Context) {
	var req menuRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "菜单名称和编码不能为空")
		return
	}

	menu, err := h.service.CreateMenu(menuInput(req))
	if err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "create-menu", "admin_menus", "success", menu.Code)
	response.Created(c, menuNodeFromModel(*menu))
}

func (h *Handler) UpdateMenu(c *gin.Context) {
	id, ok := shared.ParseID(c, "id")
	if !ok {
		return
	}
	var req menuRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "菜单名称和编码不能为空")
		return
	}

	menu, err := h.service.UpdateMenu(id, menuInput(req))
	if err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "update-menu", "admin_menus", "success", menu.Code)
	response.OK(c, menuNodeFromModel(*menu))
}

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

func (h *Handler) UpdateMenuVisible(c *gin.Context) {
	id, ok := shared.ParseID(c, "id")
	if !ok {
		return
	}
	var req visibleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "菜单显隐参数不正确")
		return
	}

	menu, err := h.service.UpdateMenuVisible(id, req.Visible)
	if err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "update-menu-visible", "admin_menus", "success", fmt.Sprintf("%s -> %t", menu.Code, req.Visible))
	response.OK(c, menuNodeFromModel(*menu))
}

func (h *Handler) SortMenus(c *gin.Context) {
	var req menuSortRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "菜单排序参数不正确")
		return
	}
	if err := h.service.SortMenus(req.Items); err != nil {
		response.BadRequest(c, err.Error())
		return
	}
	shared.OperationLog(c, h.audit, "sort-menus", "admin_menus", "success", fmt.Sprintf("%d items", len(req.Items)))
	response.OK(c, gin.H{"sorted": len(req.Items)})
}

func menuInput(req menuRequest) MenuInput {
	return MenuInput{
		ParentID:       req.ParentID,
		Label:          req.Label,
		Code:           req.Code,
		Path:           req.Path,
		Icon:           req.Icon,
		PermissionCode: req.PermissionCode,
		Sort:           req.Sort,
		Visible:        req.Visible,
	}
}
