package services

import (
	"time"

	"GoMembership/internal/models"
	"GoMembership/internal/repositories"
	"GoMembership/pkg/errors"
)

type MembershipServiceInterface interface {
	RegisterMembership(membership *models.Membership) (uint, error)
	FindMembershipByUserID(userID uint) (*models.Membership, error)
	RegisterSubscription(subscription *models.SubscriptionModel) (uint, error)
	UpdateSubscription(subscription *models.SubscriptionModel) (*models.SubscriptionModel, error)
	DeleteSubscription(id *uint, name *string) error
	GetSubscriptionModelNames() ([]string, error)
	GetSubscriptionByName(modelname *string) (*models.SubscriptionModel, error)
	GetSubscriptions(where map[string]interface{}) (*[]models.SubscriptionModel, error)
}

type MembershipService struct {
	Repo             repositories.MembershipRepositoryInterface
	SubscriptionRepo repositories.SubscriptionModelsRepositoryInterface
}

func (service *MembershipService) RegisterMembership(membership *models.Membership) (uint, error) {
	membership.StartDate = time.Now()
	return service.Repo.CreateMembership(membership)
}

func (service *MembershipService) UpdateSubscription(subscription *models.SubscriptionModel) (*models.SubscriptionModel, error) {

	existingSubscription, err := repositories.GetSubscriptionByName(&subscription.Name)
	if err != nil {
		return nil, err
	}
	if existingSubscription == nil {
		return nil, errors.ErrSubscriptionNotFound
	}
	if existingSubscription.MonthlyFee != subscription.MonthlyFee ||
		existingSubscription.HourlyRate != subscription.HourlyRate ||
		existingSubscription.Conditions != subscription.Conditions ||
		existingSubscription.IncludedPerYear != subscription.IncludedPerYear ||
		existingSubscription.IncludedPerMonth != subscription.IncludedPerMonth {
		return nil, errors.ErrInvalidSubscriptionData
	}
	subscription.ID = existingSubscription.ID
	return service.SubscriptionRepo.UpdateSubscription(subscription)

}

func (service *MembershipService) DeleteSubscription(id *uint, name *string) error {
	if *name == "" {
		return errors.ErrNoData
	}
	exists, err := repositories.GetSubscriptionByName(name)
	if err != nil {
		return err
	}
	if exists == nil {
		return errors.ErrNotFound
	}
	if *id != exists.ID {
		return errors.ErrInvalidSubscriptionData
	}
	usersInSubscription, err := repositories.GetUsersBySubscription(*id)

	if err != nil {
		return err
	}
	if len(*usersInSubscription) > 0 {
		return errors.ErrSubscriptionInUse
	}
	return service.SubscriptionRepo.DeleteSubscription(id)
}

func (service *MembershipService) FindMembershipByUserID(userID uint) (*models.Membership, error) {
	return service.Repo.FindMembershipByUserID(userID)
}

// Membership_Subscriptions
func (service *MembershipService) RegisterSubscription(subscription *models.SubscriptionModel) (uint, error) {
	return service.SubscriptionRepo.CreateSubscriptionModel(subscription)
}

func (service *MembershipService) GetSubscriptionModelNames() ([]string, error) {
	return service.SubscriptionRepo.GetSubscriptionModelNames()
}

func (service *MembershipService) GetSubscriptionByName(modelname *string) (*models.SubscriptionModel, error) {
	return repositories.GetSubscriptionByName(modelname)
}

func (service *MembershipService) GetSubscriptions(where map[string]interface{}) (*[]models.SubscriptionModel, error) {
	if where == nil {
		where = map[string]interface{}{}
	}
	return service.SubscriptionRepo.GetSubscriptions(where)
}
