package user

import (
	"context"
	"errors"

	"github.com/rede5/gohorsejobs/backend/internal/core/domain/entity"
	"github.com/rede5/gohorsejobs/backend/internal/core/dto"
	"github.com/rede5/gohorsejobs/backend/internal/core/ports"
)

type CreateUserUseCase struct {
	userRepo    ports.UserRepository
	authService ports.AuthService
}

func NewCreateUserUseCase(uRepo ports.UserRepository, auth ports.AuthService) *CreateUserUseCase {
	return &CreateUserUseCase{
		userRepo:    uRepo,
		authService: auth,
	}
}

func (uc *CreateUserUseCase) Execute(ctx context.Context, input dto.CreateUserRequest, currentTenantID string) (*dto.UserResponse, error) {
	// 1. Validate Email Uniqueness (within tenant? or global?)
	// Usually email is unique global or per tenant. Let's assume unique.
	exists, _ := uc.userRepo.FindByEmail(ctx, input.Email)
	if exists != nil {
		return nil, errors.New("user already exists")
	}

	// 2. Hash Password
	hashed, err := uc.authService.HashPassword(input.Password)
	if err != nil {
		return nil, err
	}

	// 3. Create Entity
	// Note: We enforce currentTenantID unless it's empty (SuperAdmin context) and input provides one.
	tenantID := currentTenantID
	if tenantID == "" && input.TenantID != nil {
		tenantID = *input.TenantID
	}

	user := entity.NewUser("", tenantID, input.Name, input.Email)
	user.PasswordHash = hashed

	if input.Status != nil {
		user.Status = *input.Status
	}

	// Assign roles
	for _, r := range input.Roles {
		user.AssignRole(entity.Role{Name: r})
	}

	saved, err := uc.userRepo.Save(ctx, user)
	if err != nil {
		return nil, err
	}

	// 4. Return DTO
	roles := make([]string, len(saved.Roles))
	for i, r := range saved.Roles {
		roles[i] = r.Name
	}

	return &dto.UserResponse{
		ID:        saved.ID,
		Name:      saved.Name,
		Email:     saved.Email,
		Roles:     roles,
		Status:    saved.Status,
		CreatedAt: saved.CreatedAt,
	}, nil
}
