package models

import (
	"encoding/json"
	"errors"
	"log"
	"os"
	"strings"

	"git.apinb.com/bsm-sdk/core/types"
	"git.apinb.com/bsm-sdk/core/utils"
	"gorm.io/gorm"
)

// DefaultFilePath 相对进程工作目录，与服务启动时读取配置方式一致
const DefaultFilePath = "etc/menu.json"

// File 与 etc/menu_structure.json 根结构一致
type File struct {
	Menus       []Node `json:"menus"`
	TotalLevel1 int    `json:"total_level1"`
	TotalLevel2 int    `json:"total_level2"`
}

// Node 菜单节点（可嵌套 children）
type Node struct {
	Title       string `json:"title"`
	TitleEn     string `json:"title_en"`
	Code        string `json:"code"`
	Description string `json:"description"`
	MenuPath    string `json:"menu_path"`
	Type        int8   `json:"type"`
	SortKey     int8   `json:"sort_key"`
	IsWebPage   bool   `json:"is_web_page"`
	IsNewTab    bool   `json:"is_new_tab"`
	IsFull      bool   `json:"is_full"`
	HideMenu    bool   `json:"hide_menu"`
	WebURL      string `json:"web_url"`
	Component   string `json:"component"`
	Children    []Node `json:"children"`
}

// Load 读取并解析 path
func Load(path string) (*File, error) {
	raw, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}
	var f File
	if err := json.Unmarshal(raw, &f); err != nil {
		return nil, err
	}
	return &f, nil
}

func buildPermissions(tx *gorm.DB, appID uint) ([]MgtPermission, error) {
	mf, err := Load(DefaultFilePath)
	if err != nil {
		return nil, err
	}
	if len(mf.Menus) == 0 {
		return nil, errors.New("menu is empty")
	}
	var out []MgtPermission
	if err := walkMenuTree(tx, appID, 0, mf.Menus, &out); err != nil {
		return nil, err
	}
	log.Printf("已从 %s 载入 %d 条权限（含子级）", DefaultFilePath, len(out))
	return out, nil
}

func walkMenuTree(tx *gorm.DB, appID uint, parentID uint, nodes []Node, out *[]MgtPermission) error {
	for i := range nodes {
		p, err := upsertMenuPermissionFromJSON(tx, appID, parentID, nodes[i])
		if err != nil {
			return err
		}
		*out = append(*out, p)
		if len(nodes[i].Children) > 0 {
			if err := walkMenuTree(tx, appID, p.ID, nodes[i].Children, out); err != nil {
				return err
			}
		}
	}
	return nil
}

func upsertMenuPermissionFromJSON(tx *gorm.DB, appID, parentID uint, n Node) (MgtPermission, error) {
	code := strings.TrimSpace(n.Code)
	if code == "" {
		code = "menu_" + strings.ReplaceAll(utils.UUID(), "-", "")
	}
	typ := n.Type
	if typ == 0 {
		typ = 1
	}
	p := MgtPermission{
		Std_IICUDS:  types.Std_IICUDS{Identity: utils.UUID(), Status: 1},
		Title:       n.Title,
		TitleEn:     n.TitleEn,
		Code:        code,
		Description: n.Description,
		Appid:       appID,
		ParentID:    parentID,
		MenuPath:    n.MenuPath,
		MenuIcon:    "",
		SortKey:     n.SortKey,
		Type:        typ,
		Component:   n.Component,
		IsWebPage:   n.IsWebPage,
		IsNewTab:    n.IsNewTab,
		IsFull:      n.IsFull,
		HideMenu:    n.HideMenu,
		WebUrl:      n.WebURL,
	}
	var existingPmn MgtPermission
	err := tx.Model(&MgtPermission{}).Where("code = ? AND app_id = ?", p.Code, appID).First(&existingPmn).Error
	if err == gorm.ErrRecordNotFound {
		if err := tx.Create(&p).Error; err != nil {
			return p, err
		}
		return p, nil
	}
	if err != nil {
		return p, err
	}
	p.ID = existingPmn.ID
	return p, nil
}

func builtinManagementMenuTemplates() []MgtPermission {
	return []MgtPermission{
		{Title: "系统管理", TitleEn: "System Management", Code: "system:management", Description: "系统管理菜单", MenuPath: "/system", MenuIcon: "setting", SortKey: 1, Type: 1},
		{Title: "用户管理", TitleEn: "User Management", Code: "user:management", Description: "用户管理菜单", MenuPath: "/system/user", MenuIcon: "user", SortKey: 2, Type: 1},
		{Title: "角色管理", TitleEn: "Role Management", Code: "role:management", Description: "角色管理菜单", MenuPath: "/system/role", MenuIcon: "team", SortKey: 3, Type: 1},
		{Title: "权限管理", TitleEn: "Permission Management", Code: "permission:management", Description: "权限管理菜单", MenuPath: "/system/permission", MenuIcon: "safety", SortKey: 4, Type: 1},
		{Title: "应用管理", TitleEn: "Application Management", Code: "application:management", Description: "应用管理菜单", MenuPath: "/system/application", MenuIcon: "appstore", SortKey: 5, Type: 1},
		{Title: "部门管理", TitleEn: "Department Management", Code: "department:management", Description: "部门管理菜单", MenuPath: "/system/department", MenuIcon: "apartment", SortKey: 6, Type: 1},
	}
}
