package infra

import (
	"fmt"
	"strings"

	"github.com/tidbcloud/tiinf/errs"

	"github.com/pingcap/tidb/parser"
	"github.com/pingcap/tidb/parser/ast"
	_ "github.com/pingcap/tidb/parser/test_driver"
)

const (
	BuiltinRoleNameAdmin    string = "role_admin"
	BuiltinRoleNameCDCAdmin string = "role_cdc_admin"
)

var BuiltinRoleNameSet = map[string]struct{}{
	BuiltinRoleNameAdmin:    {},
	BuiltinRoleNameCDCAdmin: {},
}

type DBUserType string

const (
	DBUserUserDefined DBUserType = "user_defined" // User Defined User
	DBUserDelegate    DBUserType = "delegate"     // delegate user
)

//func checkDBUserType(tye DBUserType) error {
//	if tye == DBUserUserDefined || tye == DBUserDelegate {
//		return nil
//	}
//	return errs.NewBadRequest("userType invalid", nil)
//}

type DBUser struct {
	Username      string
	BuiltinRole   string
	CustomRoles   []string
	Plugin        string
	AccountLocked string
}

func parseSql(sql string) ([]ast.StmtNode, error) {
	p := parser.New()

	stmtNodes, _, err := p.Parse(sql, "", "")
	if err != nil {
		return nil, err
	}

	return stmtNodes, nil
}

func getBuiltinRoles(roles []string) []string {
	var builtinRoles []string
	for _, role := range roles {
		if _, ok := BuiltinRoleNameSet[role]; ok {
			builtinRoles = append(builtinRoles, role)
		}
	}

	return builtinRoles
}

func getCustomRoles(roles []string) []string {
	var customRoles []string
	for _, role := range roles {
		if _, ok := BuiltinRoleNameSet[role]; !ok {
			customRoles = append(customRoles, role)
		}
	}

	return customRoles
}

func checkBuiltinRole(role *string) error {
	if role == nil || *role == "" {
		return nil
	}

	_, ok := BuiltinRoleNameSet[*role]
	if !ok {
		return errs.NewBadRequest("invalid builtinRole", nil)
	}
	return nil
}

func checkCustomRoles(roles []string) error {
	for _, each := range roles {
		if _, ok := BuiltinRoleNameSet[each]; ok {
			return errs.NewBadRequest(fmt.Sprintf("use builtin role in custom roles is prohibited, role=%s", each), nil)
		}
	}

	return nil
}

func parseGrantAndRevokeSql(grants, revocation string) []string {
	var out []string
	for _, each := range strings.Split(grants, ";") {
		each = strings.TrimSpace(each)
		if each != "" {
			out = append(out, each)
		}
	}
	for _, each := range strings.Split(revocation, ";") {
		each = strings.TrimSpace(each)
		if each != "" {
			out = append(out, each)
		}
	}
	return out
}

func ParseRoles(roles []string) (builtinRole string, customRoles []string) {
	for _, each := range roles {
		if _, ok := BuiltinRoleNameSet[each]; ok {
			builtinRole = each
			continue
		}

		customRoles = append(customRoles, each)
	}
	return
}
