package service

import (
	"errors"
	"fmt"

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

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

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

// Save the ride for a expected user
func (s *providerService) Save(providers []entity.ProviderResponse, user entity.User) ([]entity.Provider, error) {
	tx, err := s.svc.db.Begin()
	if err != nil {
		return nil, err
	}

	newProviders, err := tx.Provider().Save(providers, user)
	if err != nil {
		tx.Rollback()
		return nil, err
	}
	tx.Commit()

	return newProviders, nil
}

func (s *providerService) GetAll(user entity.User) ([]entity.Provider, error) {
	return s.svc.db.Provider().GetAll(user)
}

func (s *providerService) Get(query string, lat float64, long float64, distance int64, planCode string, productID string, mukID string, internalID string, sort string, user entity.User) ([]entity.Provider, error) {
	return s.svc.db.Provider().Get(query, lat, long, distance, planCode, productID, mukID, internalID, sort, user)
}

func (s *providerService) GetByMukID(mukID string, user entity.User) (entity.Provider, error) {
	provider, err := s.svc.db.Provider().GetByMukID(mukID, user)
	if err != nil {
		return provider, err
	}

	organization, err := s.svc.db.Organization().GetByTypeAndReferenceID("provider", provider.ProviderID, user)
	if err != nil {
		return provider, err
	}

	provider.Organization = organization
	return provider, nil
}

func (s *providerService) GetByUUID(providerUUID string, user entity.User) (entity.Provider, error) {
	provider, err := s.svc.db.Provider().GetByUUID(providerUUID, user)
	if err != nil {
		fmt.Println("providerService.GetByUUID: Provider UUID: ", providerUUID)
		fmt.Println("providerService.GetByUUID: Provider Error: ", err.Error())
		return provider, err
	}

	organization, err := s.svc.db.Organization().GetByTypeAndReferenceID("provider", provider.ProviderID, user)
	if err != nil {
		fmt.Println("providerService.GetByUUID: OrganizationByType ProviderID : ", provider.ProviderID)
		fmt.Println("providerService.GetByUUID: OrganizationByType Error: ", err.Error())
		return provider, err
	}

	provider.Organization = organization
	return provider, nil
}

func (s *providerService) GetByNPI(NPI string, user entity.User) (entity.Provider, error) {
	provider, err := s.svc.db.Provider().GetByNPI(NPI, user)
	if err != nil {
		return provider, err
	}

	organization, err := s.svc.db.Organization().GetByTypeAndReferenceID("provider", provider.ProviderID, user)
	if err != nil {
		return provider, err
	}

	provider.Organization = organization
	return provider, nil
}

func (s *providerService) GetByOrganization(organizationUUID string, user entity.User) (entity.Provider, error) {
	organization, err := s.svc.db.Organization().GetByUUID(organizationUUID, user)
	if err != nil {
		return entity.Provider{}, err
	}

	if organization.Type.Key != "provider" {
		return entity.Provider{}, errors.New("invalid organization")
	}

	provider, err := s.svc.db.Provider().GetByID(organization.ReferenceID, user)
	if err != nil {
		return entity.Provider{}, err
	}

	return provider, nil
}
