package ast

import (
	"fmt"
	"go/ast"
	"go/token"
)

// Type AST类型
type Type string

func (r Type) String() string {
	return string(r)
}

func (r Type) Group() string {
	switch r {
	case TypePackageApiEnter:
		return "ApiGroup"
	case TypePackageRouterEnter:
		return "RouterGroup"
	case TypePackageServiceEnter:
		return "ServiceGroup"
	case TypePackageApiModuleEnter:
		return "ApiGroup"
	case TypePackageRouterModuleEnter:
		return "RouterGroup"
	case TypePackageServiceModuleEnter:
		return "ServiceGroup"
	case TypePluginApiEnter:
		return "api"
	case TypePluginRouterEnter:
		return "router"
	case TypePluginServiceEnter:
		return "service"
	default:
		return ""
	}
}

const (
	TypePackageApiEnter           = "PackageApiEnter"
	TypePackageRouterEnter        = "PackageRouterEnter"
	TypePackageServiceEnter       = "PackageServiceEnter"
	TypePackageApiModuleEnter     = "PackageApiModuleEnter"
	TypePackageRouterModuleEnter  = "PackageRouterModuleEnter"
	TypePackageServiceModuleEnter = "PackageServiceModuleEnter"
	TypePackageInitializeGorm     = "PackageInitializeGorm"
	TypePackageInitializeRouter   = "PackageInitializeRouter"
	TypePluginGen                 = "PluginGen"
	TypePluginApiEnter            = "PluginApiEnter"
	TypePluginInitializeV1        = "PluginInitializeV1"
	TypePluginInitializeV2        = "PluginInitializeV2"
	TypePluginRouterEnter         = "PluginRouterEnter"
	TypePluginServiceEnter        = "PluginServiceEnter"
	TypePluginInitializeApi       = "PluginInitializeApi"
	TypePluginInitializeGorm      = "PluginInitializeGorm"
	TypePluginInitializeMenu      = "PluginInitializeMenu"
	TypePluginInitializeRouter    = "PluginInitializeRouter"
)

// SysBaseMenu 菜单结构（用于AST生成）
type SysBaseMenu struct {
	ParentId   uint
	Path       string
	Name       string
	Hidden     bool
	Component  string
	Sort       int
	Title      string
	Icon       string
	Parameters []SysBaseMenuParameter
	MenuBtn    []SysBaseMenuBtn
}

// SysBaseMenuParameter 菜单参数
type SysBaseMenuParameter struct {
	Type  string
	Key   string
	Value string
}

// SysBaseMenuBtn 菜单按钮
type SysBaseMenuBtn struct {
	Name string
	Desc string
}

// SysApi API结构
type SysApi struct {
	Path        string
	Description string
	ApiGroup    string
	Method      string
}

// CreateMenuStructAst 创建菜单结构AST
func CreateMenuStructAst(menus []SysBaseMenu) *[]ast.Expr {
	var menuElts []ast.Expr
	for i := range menus {
		elts := []ast.Expr{
			&ast.KeyValueExpr{
				Key:   &ast.Ident{Name: "ParentId"},
				Value: &ast.BasicLit{Kind: token.INT, Value: "0"},
			},
			&ast.KeyValueExpr{
				Key:   &ast.Ident{Name: "Path"},
				Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", menus[i].Path)},
			},
			&ast.KeyValueExpr{
				Key:   &ast.Ident{Name: "Name"},
				Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", menus[i].Name)},
			},
			&ast.KeyValueExpr{
				Key:   &ast.Ident{Name: "Hidden"},
				Value: &ast.Ident{Name: "false"},
			},
			&ast.KeyValueExpr{
				Key:   &ast.Ident{Name: "Component"},
				Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", menus[i].Component)},
			},
			&ast.KeyValueExpr{
				Key:   &ast.Ident{Name: "Sort"},
				Value: &ast.BasicLit{Kind: token.INT, Value: fmt.Sprintf("%d", menus[i].Sort)},
			},
			&ast.KeyValueExpr{
				Key: &ast.Ident{Name: "Meta"},
				Value: &ast.CompositeLit{
					Type: &ast.SelectorExpr{
						X:   &ast.Ident{Name: "model"},
						Sel: &ast.Ident{Name: "Meta"},
					},
					Elts: []ast.Expr{
						&ast.KeyValueExpr{
							Key:   &ast.Ident{Name: "Title"},
							Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", menus[i].Title)},
						},
						&ast.KeyValueExpr{
							Key:   &ast.Ident{Name: "Icon"},
							Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", menus[i].Icon)},
						},
					},
				},
			},
		}

		if len(menus[i].Parameters) > 0 {
			var paramElts []ast.Expr
			for _, param := range menus[i].Parameters {
				paramElts = append(paramElts, &ast.CompositeLit{
					Type: &ast.SelectorExpr{
						X:   &ast.Ident{Name: "model"},
						Sel: &ast.Ident{Name: "SysBaseMenuParameter"},
					},
					Elts: []ast.Expr{
						&ast.KeyValueExpr{
							Key:   &ast.Ident{Name: "Type"},
							Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", param.Type)},
						},
						&ast.KeyValueExpr{
							Key:   &ast.Ident{Name: "Key"},
							Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", param.Key)},
						},
						&ast.KeyValueExpr{
							Key:   &ast.Ident{Name: "Value"},
							Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", param.Value)},
						},
					},
				})
			}
			elts = append(elts, &ast.KeyValueExpr{
				Key: &ast.Ident{Name: "Parameters"},
				Value: &ast.CompositeLit{
					Type: &ast.ArrayType{
						Elt: &ast.SelectorExpr{
							X:   &ast.Ident{Name: "model"},
							Sel: &ast.Ident{Name: "SysBaseMenuParameter"},
						},
					},
					Elts: paramElts,
				},
			})
		}

		if len(menus[i].MenuBtn) > 0 {
			var btnElts []ast.Expr
			for _, btn := range menus[i].MenuBtn {
				btnElts = append(btnElts, &ast.CompositeLit{
					Type: &ast.SelectorExpr{
						X:   &ast.Ident{Name: "model"},
						Sel: &ast.Ident{Name: "SysBaseMenuBtn"},
					},
					Elts: []ast.Expr{
						&ast.KeyValueExpr{
							Key:   &ast.Ident{Name: "Name"},
							Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", btn.Name)},
						},
						&ast.KeyValueExpr{
							Key:   &ast.Ident{Name: "Desc"},
							Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", btn.Desc)},
						},
					},
				})
			}
			elts = append(elts, &ast.KeyValueExpr{
				Key: &ast.Ident{Name: "MenuBtn"},
				Value: &ast.CompositeLit{
					Type: &ast.ArrayType{
						Elt: &ast.SelectorExpr{
							X:   &ast.Ident{Name: "model"},
							Sel: &ast.Ident{Name: "SysBaseMenuBtn"},
						},
					},
					Elts: btnElts,
				},
			})
		}

		menuElts = append(menuElts, &ast.CompositeLit{
			Type: nil,
			Elts: elts,
		})
	}
	return &menuElts
}

// CreateApiStructAst 创建API结构AST
func CreateApiStructAst(apis []SysApi) *[]ast.Expr {
	var apiElts []ast.Expr
	for i := range apis {
		elts := []ast.Expr{
			&ast.KeyValueExpr{
				Key:   &ast.Ident{Name: "Path"},
				Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", apis[i].Path)},
			},
			&ast.KeyValueExpr{
				Key:   &ast.Ident{Name: "Description"},
				Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", apis[i].Description)},
			},
			&ast.KeyValueExpr{
				Key:   &ast.Ident{Name: "ApiGroup"},
				Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", apis[i].ApiGroup)},
			},
			&ast.KeyValueExpr{
				Key:   &ast.Ident{Name: "Method"},
				Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", apis[i].Method)},
			},
		}
		apiElts = append(apiElts, &ast.CompositeLit{
			Type: nil,
			Elts: elts,
		})
	}
	return &apiElts
}
