package native

import (
	"context"

	"github.com/tech/sendico/pkg/auth/management"
	"github.com/tech/sendico/pkg/db/policy"
	"github.com/tech/sendico/pkg/db/role"
	"github.com/tech/sendico/pkg/mlogger"
	"github.com/tech/sendico/pkg/model"
	"go.uber.org/zap"
)

// NativeManager implements the auth.Manager interface by aggregating Role and Permission managers.
type NativeManager struct {
	logger      mlogger.Logger
	roleManager management.Role
	permManager management.Permission
}

// NewManager creates a new CasbinManager with specified domains and role-domain mappings.
func NewManager(
	l mlogger.Logger,
	pdb policy.DB,
	rdb role.DB,
	enforcer *Enforcer,
) (*NativeManager, error) {
	logger := l.Named("manager")

	var pdesc model.PolicyDescription
	if err := pdb.GetBuiltInPolicy(context.Background(), "roles", &pdesc); err != nil {
		logger.Warn("Failed to fetch roles permission reference", zap.Error(err))
		return nil, err
	}

	return &NativeManager{
		logger:      logger,
		roleManager: NewRoleManager(logger, enforcer, pdesc.ID, rdb),
		permManager: NewPermissionManager(logger, enforcer),
	}, nil
}

// Permission returns the Permission manager.
func (m *NativeManager) Permission() management.Permission {
	return m.permManager
}

// Role returns the Role manager.
func (m *NativeManager) Role() management.Role {
	return m.roleManager
}
