package service

import (
	"context"

	"eslogad-be/internal/contract"
	"eslogad-be/internal/entities"
	"eslogad-be/internal/transformer"

	"github.com/google/uuid"
)

type UserServiceImpl struct {
	userProcessor UserProcessor
	titleRepo     TitleRepository
}

type TitleRepository interface {
	ListAll(ctx context.Context) ([]entities.Title, error)
}

func NewUserService(userProcessor UserProcessor, titleRepo TitleRepository) *UserServiceImpl {
	return &UserServiceImpl{
		userProcessor: userProcessor,
		titleRepo:     titleRepo,
	}
}

func (s *UserServiceImpl) CreateUser(ctx context.Context, req *contract.CreateUserRequest) (*contract.UserResponse, error) {
	return s.userProcessor.CreateUser(ctx, req)
}

func (s *UserServiceImpl) UpdateUser(ctx context.Context, id uuid.UUID, req *contract.UpdateUserRequest) (*contract.UserResponse, error) {
	return s.userProcessor.UpdateUser(ctx, id, req)
}

func (s *UserServiceImpl) DeleteUser(ctx context.Context, id uuid.UUID) error {
	return s.userProcessor.DeleteUser(ctx, id)
}

func (s *UserServiceImpl) GetUserByID(ctx context.Context, id uuid.UUID) (*contract.UserResponse, error) {
	return s.userProcessor.GetUserByID(ctx, id)
}

func (s *UserServiceImpl) GetUserByEmail(ctx context.Context, email string) (*contract.UserResponse, error) {
	return s.userProcessor.GetUserByEmail(ctx, email)
}

func (s *UserServiceImpl) ListUsers(ctx context.Context, req *contract.ListUsersRequest) (*contract.ListUsersResponse, error) {
	page := req.Page
	if page <= 0 {
		page = 1
	}
	limit := req.Limit
	if limit <= 0 {
		limit = 10
	}

	userResponses, totalCount, err := s.userProcessor.ListUsersWithFilters(ctx, req)
	if err != nil {
		return nil, err
	}

	return &contract.ListUsersResponse{
		Users:      userResponses,
		Pagination: transformer.CreatePaginationResponse(totalCount, page, limit),
	}, nil
}

func (s *UserServiceImpl) ChangePassword(ctx context.Context, userID uuid.UUID, req *contract.ChangePasswordRequest) error {
	return s.userProcessor.ChangePassword(ctx, userID, req)
}

func (s *UserServiceImpl) GetProfile(ctx context.Context, userID uuid.UUID) (*contract.UserProfileResponse, error) {
	prof, err := s.userProcessor.GetUserProfile(ctx, userID)
	if err != nil {
		return nil, err
	}
	if roles, err := s.userProcessor.GetUserRoles(ctx, userID); err == nil {
		prof.Roles = roles
	}
	return prof, nil
}

func (s *UserServiceImpl) UpdateProfile(ctx context.Context, userID uuid.UUID, req *contract.UpdateUserProfileRequest) (*contract.UserProfileResponse, error) {
	return s.userProcessor.UpdateUserProfile(ctx, userID, req)
}

func (s *UserServiceImpl) ListTitles(ctx context.Context) (*contract.ListTitlesResponse, error) {
	if s.titleRepo == nil {
		return &contract.ListTitlesResponse{Titles: []contract.TitleResponse{}}, nil
	}
	titles, err := s.titleRepo.ListAll(ctx)
	if err != nil {
		return nil, err
	}
	return &contract.ListTitlesResponse{Titles: transformer.TitlesToContract(titles)}, nil
}

// GetActiveUsersForMention retrieves active users for mention purposes
func (s *UserServiceImpl) GetActiveUsersForMention(ctx context.Context, search *string, limit int) ([]contract.UserResponse, error) {
	return s.userProcessor.GetActiveUsersForMention(ctx, search, limit)
}
