package service

import (
	"context"
	"errors"
	"strings"

	"wucher/internal/domain/auth"
)

type RoleService struct {
	repo auth.RoleRepository
}

func NewRoleService(repo auth.RoleRepository) *RoleService {
	return &RoleService{repo: repo}
}

func (s *RoleService) Create(ctx context.Context, role *auth.Role) error {
	if strings.TrimSpace(role.Name) == "" {
		return errors.New("name is required")
	}
	return s.repo.CreateRole(ctx, role)
}

func (s *RoleService) Update(ctx context.Context, role *auth.Role) error {
	if strings.TrimSpace(role.Name) == "" {
		return errors.New("name is required")
	}
	return s.repo.UpdateRole(ctx, role)
}

func (s *RoleService) Delete(ctx context.Context, id []byte) error {
	return s.repo.DeleteRole(ctx, id)
}

func (s *RoleService) GetByID(ctx context.Context, id []byte) (*auth.Role, error) {
	return s.repo.GetRoleByID(ctx, id)
}

func (s *RoleService) GetByName(ctx context.Context, name string) (*auth.Role, error) {
	return s.repo.GetRoleByName(ctx, name)
}

func (s *RoleService) GetPermissionByID(ctx context.Context, id []byte) (*auth.Permission, error) {
	return s.repo.GetPermissionByID(ctx, id)
}

func (s *RoleService) GetPermissionByKey(ctx context.Context, key string) (*auth.Permission, error) {
	return s.repo.GetPermissionByKey(ctx, key)
}

func (s *RoleService) UpdatePermission(ctx context.Context, permission *auth.Permission) error {
	if strings.TrimSpace(permission.Name) == "" {
		return errors.New("name is required")
	}
	if strings.TrimSpace(permission.Key) == "" {
		return errors.New("key is required")
	}
	return s.repo.UpdatePermission(ctx, permission)
}

func (s *RoleService) AssignPermission(ctx context.Context, roleID, permissionID []byte) (*auth.RolePermission, error) {
	return s.repo.AssignPermission(ctx, roleID, permissionID)
}

func (s *RoleService) RemovePermission(ctx context.Context, roleID, permissionID []byte) error {
	return s.repo.RemovePermission(ctx, roleID, permissionID)
}

func (s *RoleService) ListPermissions(ctx context.Context, filter, sort string, limit, offset int) ([]auth.Permission, int64, error) {
	return s.repo.ListPermissions(ctx, filter, normalizePermissionSort(sort), limit, offset)
}

func (s *RoleService) ListPermissionsByRoleID(ctx context.Context, roleID []byte) ([]auth.Permission, error) {
	return s.repo.ListPermissionsByRoleID(ctx, roleID)
}

func (s *RoleService) List(ctx context.Context, filterName, sort string, limit, offset int) ([]auth.Role, int64, error) {
	return s.repo.ListRoles(ctx, filterName, normalizeSort(sort), limit, offset)
}

func normalizeSort(sort string) string {
	return normalizeSortByRules(sort,
		sortField("name"),
		sortField("created_at"),
		sortField("updated_at"),
	)
}

func normalizePermissionSort(sort string) string {
	return normalizeSortByRules(sort,
		sortField("name"),
		sortField("`key`", "key"),
		sortField("created_at"),
		sortField("updated_at"),
	)
}
