package rbac

import (
	"errors"
	"strings"

	"hyapp-admin-server/internal/model"
	"hyapp-admin-server/internal/repository"
)

type RBACService struct {
	store *repository.Store
}

type PermissionInput struct {
	Name        string
	Code        string
	Kind        string
	Description string
}

type RoleInput struct {
	Name          string
	Code          string
	Description   string
	PermissionIDs []uint
}

type DataScopeInput struct {
	Scopes []DataScopeItem
}

type DataScopeItem struct {
	ScopeType  string
	ScopeValue string
}

func NewService(store *repository.Store) *RBACService {
	return &RBACService{store: store}
}

func (s *RBACService) ListPermissions() ([]model.Permission, error) {
	return s.store.ListPermissions()
}

func (s *RBACService) CreatePermission(input PermissionInput) (*model.Permission, error) {
	permission := model.Permission{Name: input.Name, Code: input.Code, Kind: input.Kind, Description: input.Description}
	if err := s.store.CreatePermission(&permission); err != nil {
		return nil, err
	}
	return &permission, nil
}

func (s *RBACService) UpdatePermission(id uint, input PermissionInput) (*model.Permission, error) {
	return s.store.UpdatePermission(id, model.Permission{Name: input.Name, Code: input.Code, Kind: input.Kind, Description: input.Description})
}

func (s *RBACService) DeletePermission(id uint) error {
	return s.store.DeletePermission(id)
}

func (s *RBACService) SyncPermissions() error {
	return s.store.SyncDefaultPermissions()
}

func (s *RBACService) ListRoles() ([]model.Role, error) {
	return s.store.ListRoles()
}

func (s *RBACService) CreateRole(input RoleInput) (*model.Role, error) {
	role := model.Role{Name: input.Name, Code: input.Code, Description: input.Description}
	if err := s.store.CreateRole(&role, input.PermissionIDs); err != nil {
		return nil, err
	}
	return &role, nil
}

func (s *RBACService) UpdateRole(id uint, input RoleInput) (*model.Role, error) {
	return s.store.UpdateRole(id, model.Role{Name: input.Name, Code: input.Code, Description: input.Description}, nil)
}

func (s *RBACService) DeleteRole(id uint) error {
	return s.store.DeleteRole(id)
}

func (s *RBACService) ReplaceRolePermissions(id uint, permissionIDs []uint) error {
	return s.store.ReplaceRolePermissions(id, permissionIDs)
}

func (s *RBACService) ListRoleDataScopes(id uint) ([]model.DataScope, error) {
	return s.store.ListRoleDataScopes(id)
}

func (s *RBACService) ReplaceRoleDataScopes(id uint, input DataScopeInput) error {
	scopes := make([]model.DataScope, 0, len(input.Scopes))
	for _, item := range input.Scopes {
		scopeType := strings.TrimSpace(item.ScopeType)
		scopeValue := strings.TrimSpace(item.ScopeValue)
		if !validDataScope(scopeType, scopeValue) {
			return errors.New("invalid data scope")
		}
		scopes = append(scopes, model.DataScope{ScopeType: scopeType, ScopeValue: scopeValue})
	}
	return s.store.ReplaceRoleDataScopes(id, scopes)
}

func validDataScope(scopeType string, scopeValue string) bool {
	switch scopeType {
	case "all":
		return scopeValue == "all"
	case "team":
		return scopeValue != ""
	case "self":
		return scopeValue == "self"
	default:
		return false
	}
}
