package services

import (
	"astrology-api/dto"
	models "astrology-api/models/usermodel"
	"astrology-api/repositories"
	"errors"
)

type FollowerService interface {

	// Follow
	FollowAstrologer(userID uint, astrologerID uint) (*models.UserFollowing, error)

	// Unfollow
	UnfollowAstrologer(userID uint, astrologerID uint) error

	// My Following List
	GetFollowingList(userID uint, req dto.GetFollowerRequest) ([]dto.FollowingResponse, int64, error)

	// Astrologer Followers
	GetAstrologerFollowers(astrologerID uint) ([]dto.FollowerResponse, int64, error)

	// Check Follow Status
	IsFollowing(userID uint, astrologerID uint) (bool, error)

	// Followers Count
	GetFollowersCount(astrologerID uint) (int64, error)
}

type followerService struct {
	followerRepository   repositories.FollowerRepository
	astrologerRepository repositories.AstrologerRepository
}

func NewFollowerService(
	followerRepository repositories.FollowerRepository,
	astrologerRepository repositories.AstrologerRepository,
) FollowerService {

	return &followerService{
		followerRepository:   followerRepository,
		astrologerRepository: astrologerRepository,
	}
}

func (s *followerService) FollowAstrologer(userID uint, astrologerID uint) (*models.UserFollowing, error) {

	// Check astrologer exists
	astrologer, err := s.astrologerRepository.GetAstrologerByID(dto.GetAstrologerByIDRequest{AstrologerID: astrologerID})
	if err != nil {
		return nil, err
	}

	if astrologer == nil {
		return nil, errors.New("astrologer not found")
	}

	// Already followed?
	isFollowing, err := s.followerRepository.IsFollowing(userID, astrologerID)
	if err != nil {
		return nil, err
	}

	if isFollowing {
		return nil, errors.New("already following this astrologer")
	}

	return s.followerRepository.AddFollowing(userID, astrologerID)

}

func (s *followerService) UnfollowAstrologer(
	userID uint,
	astrologerID uint,
) error {

	isFollowing, err := s.followerRepository.IsFollowing(userID, astrologerID)
	if err != nil {
		return err
	}

	if !isFollowing {
		return errors.New("you are not following this astrologer")
	}

	return s.followerRepository.RemoveFollowing(userID, astrologerID)
}

func (s *followerService) GetFollowingList(
	userID uint,
	req dto.GetFollowerRequest,
) ([]dto.FollowingResponse, int64, error) {

	list, total, err := s.followerRepository.GetFollowingList(
		userID,
		req.StartIndex,
		req.FetchRecord,
	)

	if err != nil {
		return nil, 0, err
	}

	return list, total, nil
}

func (s *followerService) GetAstrologerFollowers(
	astrologerID uint,
) ([]dto.FollowerResponse, int64, error) {

	return s.followerRepository.GetAstrologerFollowers(astrologerID)
}

func (s *followerService) IsFollowing(
	userID uint,
	astrologerID uint,
) (bool, error) {

	return s.followerRepository.IsFollowing(userID, astrologerID)
}

func (s *followerService) GetFollowersCount(
	astrologerID uint,
) (int64, error) {

	return s.followerRepository.GetFollowersCount(astrologerID)
}
