package applicationservice

import (
	"fmt"

	"bitbucket.org/nemt/nemt-portal-api/application/entitymapping"
	"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
	"bitbucket.org/nemt/nemt-portal-api/domain/service"
	"bitbucket.org/nemt/nemt-portal-api/infra/errors"
)

// rideService holds methods to user application service
type visitService struct {
	svc       *service.Service
	mapEntity *entitymapping.Mapper
}

// newUserService returns a userService instance
func newVisitService(svc *service.Service, mapper *entitymapping.Mapper) *visitService {
	return &visitService{
		svc:       svc,
		mapEntity: mapper,
	}
}

func (s *visitService) Save(visit viewmodel.Visit) (viewmodel.Visit, error) {
	entity := s.mapEntity.Visit.ToVisitEntity(visit)
	for _, a := range visit.User.Addresses {
		if a.AddressType == "home" {
			address, err := s.svc.Users.GetAddressByUUID(a.UUID)
			if err != nil {
				fmt.Println("Application Visit: Address UUID: ", a.UUID)
				fmt.Println("Application Visit: Address Error: ", err.Error())
				return viewmodel.Visit{}, err
			}

			entity.PickupAddressID = address.ID
			entity.Pickup.Address = address.Address
			entity.Pickup.ID = address.UUID
			entity.Pickup.Latitude = address.Latitude
			entity.Pickup.Longitude = address.Longitude
			entity.Pickup.Name = address.Name
		}
	}

	provider, err := s.svc.Provider.GetByUUID(entity.Provider.ProviderUUID, entity.CreatedUser)
	if err != nil {
		fmt.Println("Application Visit: Provider UUID: ", entity.Provider.ProviderUUID)
		fmt.Println("Application Visit: Provider Error: ", err.Error())
		return viewmodel.Visit{}, errors.Wrap(err)
	}
	entity.Provider = provider

	retVal, err := s.svc.Visits.Create(entity)
	if err != nil {
		fmt.Println("Application Visit: Create Visit Error: ", err.Error())
		return viewmodel.Visit{}, errors.Wrap(err)
	}

	return s.mapEntity.Visit.ToVisitModel(retVal), err
}

// Save a new ride
func (s *visitService) Create(visit viewmodel.Visit) (viewmodel.Visit, error) {
	entity := s.mapEntity.Visit.ToVisitEntity(visit)
	retVal, err := s.svc.Visits.Create(entity)
	if err != nil {
		return viewmodel.Visit{}, errors.Wrap(err)
	}

	return s.mapEntity.Visit.ToVisitModel(retVal), err
}

// Save a new ride
func (s *visitService) GetAll(user viewmodel.User) ([]viewmodel.Visit, error) {
	eUser := s.mapEntity.User.ToUserEntity(user)
	retVal, err := s.svc.Visits.GetAll(eUser)
	if err != nil {
		return nil, errors.Wrap(err)
	}

	return s.mapEntity.Visit.ToVisitModelSlice(retVal), err
}

// Save a new ride
func (s *visitService) GetByUUID(visitUUID string, user viewmodel.User) (viewmodel.Visit, error) {
	eUser := s.mapEntity.User.ToUserEntity(user)
	retVal, err := s.svc.Visits.GetByUUID(visitUUID, eUser)
	if err != nil {
		fmt.Println("Visit Application: Error getting visit: ", err.Error())
		return viewmodel.Visit{}, errors.Wrap(err)
	}

	visitUser, err := s.svc.Users.GetByUUID(retVal.User.UUID, "US")
	if err != nil {
		fmt.Println("Visit Application: Error getting user: ", err.Error())
		return viewmodel.Visit{}, errors.Wrap(err)
	}
	retVal.User = visitUser

	provider, err := s.svc.Provider.GetByUUID(retVal.Provider.ProviderUUID, eUser)
	if err != nil {
		fmt.Println("Visit Application: Error getting provider: ", err.Error())
		return viewmodel.Visit{}, errors.Wrap(err)
	}
	retVal.Provider = provider

	return s.mapEntity.Visit.ToVisitModel(retVal), err
}
