package service

import (
	"fmt"

	"bitbucket.org/nemt/nemt-portal-api/domain/entity"
)

// userService is the domain service for user operations
type userService struct {
	svc *Service
}

// newUserService returns an instance of userService
func newUserService(svc *Service) *userService {
	return &userService{
		svc: svc,
	}
}

// GetAll returns a list of users
func (s *userService) GetAll() (list []entity.User, err error) {
	return s.svc.db.Users().GetAll()
}

// GetByID returns a specific user by its ID
func (s *userService) GetByID(userID int64) (entity.User, error) {
	return s.svc.db.Users().GetByID(userID)
}

// GetByID returns a specific user by its ID
func (s *userService) GetByUUID(uuid string, profile string) (entity.User, error) {
	return s.svc.db.Users().GetByUUID(uuid, profile)
}

func (s *userService) GetByMemberID(memberID string) (entity.User, error) {
	return s.svc.db.Users().GetByMemberID(memberID)
}

func (s *userService) GetByEmail(email string) (entity.User, error) {
	return s.svc.db.Users().GetByEmail(email)
}

// Login returns a specific user by email and pass
func (s *userService) Login(email string, pass string) (entity.User, error) {
	return s.svc.db.Users().Login(email, pass)
}

// Login returns a specific user by email and pass
func (s *userService) FullLogin(loginType string, key string, pass string, profile string) (entity.User, error) {
	return s.svc.db.Users().FullLogin(loginType, key, pass, profile)
}

// Login returns a specific user by email and pass
func (s *userService) Create(user entity.User) (entity.User, error) {
	return s.svc.db.Users().Create(user)
}

func (s *userService) CreateBulk(users []entity.User) ([]entity.User, error) {
	tx, err := s.svc.db.Begin()
	if err != nil {
		return nil, err
	}

	for i, _ := range users {
		users[i], err = tx.Users().Create(users[i])
		if err != nil {
			fmt.Println(fmt.Sprintf("Email %s got error: %s", users[i].Email, err.Error()))
			tx.Rollback()
			return nil, err
		}
		fmt.Println(fmt.Sprintf("Email %s created", users[i].Email))
	}

	tx.Commit()
	return users, nil
}

func (s *userService) UpdateLogin(user entity.User) error {
	return s.svc.db.Users().UpdateLogin(user)
}

// GetUsersByProfile returns a list of users by profile
func (s *userService) GetUsersByProfile(profile string) ([]entity.User, error) {
	return s.svc.db.Users().GetUsersByProfile(profile)
}

func (s *userService) RemoveAddress(addressUUID string) error {
	return s.svc.db.Users().RemoveAddress(addressUUID)
}

// SaveAddress returns a list of users by profile
func (s *userService) SaveAddress(address entity.Address) (entity.Address, error) {
	return s.svc.db.Users().SaveAddress(address)
}

func (s *userService) SaveContact(contact entity.ContactInfo) (entity.ContactInfo, error) {
	user, err := s.svc.db.Users().GetByUUID(contact.User.UUID, "")
	if err != nil {
		return entity.ContactInfo{}, nil
	}

	contact.User = user
	return s.svc.db.Users().SaveContact(contact)
}

func (s *userService) RemoveContact(contact entity.ContactInfo) (entity.ContactInfo, error) {
	user, err := s.svc.db.Users().GetByUUID(contact.User.UUID, "")
	if err != nil {
		return entity.ContactInfo{}, nil
	}

	contact.User = user
	return s.svc.db.Users().RemoveContact(contact)
}

// GetAddressByUUID returns a list of users by profile
func (s *userService) GetAddressByUUID(addressUUID string) (entity.Address, error) {
	return s.svc.db.Users().GetAddressByUUID(addressUUID)
}

func (s *userService) GetContactType() (retVal []entity.ContactType, err error) {
	return s.svc.db.Users().GetContactType()
}
