package user

import (
	"context"
	"strings"

	"hyapp/pkg/xerr"
	userdomain "hyapp/services/user-service/internal/domain/user"
)

const (
	defaultSocialPageSize = 20
	maxSocialPageSize     = 100
)

// RecordProfileVisit 记录访问关系；自己访问自己不进入访问计数。
func (s *Service) RecordProfileVisit(ctx context.Context, visitorUserID int64, targetUserID int64) (bool, userdomain.ProfileStats, error) {
	if visitorUserID <= 0 || targetUserID <= 0 {
		return false, userdomain.ProfileStats{}, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if visitorUserID == targetUserID {
		return false, userdomain.ProfileStats{}, xerr.New(xerr.InvalidArgument, "cannot visit self")
	}
	if s.userRepository == nil {
		return false, userdomain.ProfileStats{}, xerr.New(xerr.Unavailable, "user repository is not configured")
	}
	return s.userRepository.RecordProfileVisit(ctx, visitorUserID, targetUserID, s.now().UnixMilli())
}

func (s *Service) ListProfileVisitors(ctx context.Context, userID int64, page int32, pageSize int32) ([]userdomain.ProfileVisitRecord, int64, error) {
	if userID <= 0 {
		return nil, 0, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if s.userRepository == nil {
		return nil, 0, xerr.New(xerr.Unavailable, "user repository is not configured")
	}
	page, pageSize = normalizeSocialPage(page, pageSize)
	return s.userRepository.ListProfileVisitors(ctx, userID, page, pageSize)
}

func (s *Service) FollowUser(ctx context.Context, followerUserID int64, followeeUserID int64) (userdomain.ProfileStats, error) {
	if followerUserID <= 0 || followeeUserID <= 0 {
		return userdomain.ProfileStats{}, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if followerUserID == followeeUserID {
		return userdomain.ProfileStats{}, xerr.New(xerr.InvalidArgument, "cannot follow self")
	}
	if s.userRepository == nil {
		return userdomain.ProfileStats{}, xerr.New(xerr.Unavailable, "user repository is not configured")
	}
	return s.userRepository.FollowUser(ctx, followerUserID, followeeUserID, s.now().UnixMilli())
}

func (s *Service) UnfollowUser(ctx context.Context, followerUserID int64, followeeUserID int64) (userdomain.ProfileStats, error) {
	if followerUserID <= 0 || followeeUserID <= 0 {
		return userdomain.ProfileStats{}, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if followerUserID == followeeUserID {
		return userdomain.ProfileStats{}, xerr.New(xerr.InvalidArgument, "cannot unfollow self")
	}
	if s.userRepository == nil {
		return userdomain.ProfileStats{}, xerr.New(xerr.Unavailable, "user repository is not configured")
	}
	return s.userRepository.UnfollowUser(ctx, followerUserID, followeeUserID, s.now().UnixMilli())
}

func (s *Service) ListFollowing(ctx context.Context, userID int64, page int32, pageSize int32, cursorUpdatedAtMS int64, cursorUserID int64) ([]userdomain.FollowRecord, int64, error) {
	if userID <= 0 {
		return nil, 0, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if s.userRepository == nil {
		return nil, 0, xerr.New(xerr.Unavailable, "user repository is not configured")
	}
	page, pageSize = normalizeSocialPage(page, pageSize)
	return s.userRepository.ListFollowing(ctx, userID, page, pageSize, cursorUpdatedAtMS, cursorUserID)
}

func (s *Service) ApplyFriend(ctx context.Context, requesterUserID int64, targetUserID int64) (userdomain.FriendApplication, bool, error) {
	if requesterUserID <= 0 || targetUserID <= 0 {
		return userdomain.FriendApplication{}, false, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if requesterUserID == targetUserID {
		return userdomain.FriendApplication{}, false, xerr.New(xerr.InvalidArgument, "cannot add self as friend")
	}
	if s.userRepository == nil {
		return userdomain.FriendApplication{}, false, xerr.New(xerr.Unavailable, "user repository is not configured")
	}
	return s.userRepository.ApplyFriend(ctx, requesterUserID, targetUserID, s.now().UnixMilli())
}

func (s *Service) AcceptFriendApplication(ctx context.Context, accepterUserID int64, requesterUserID int64) (userdomain.FriendRecord, error) {
	if accepterUserID <= 0 || requesterUserID <= 0 {
		return userdomain.FriendRecord{}, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if accepterUserID == requesterUserID {
		return userdomain.FriendRecord{}, xerr.New(xerr.InvalidArgument, "cannot accept self friend request")
	}
	if s.userRepository == nil {
		return userdomain.FriendRecord{}, xerr.New(xerr.Unavailable, "user repository is not configured")
	}
	return s.userRepository.AcceptFriendApplication(ctx, accepterUserID, requesterUserID, s.now().UnixMilli())
}

func (s *Service) DeleteFriend(ctx context.Context, userID int64, friendUserID int64) (bool, error) {
	if userID <= 0 || friendUserID <= 0 {
		return false, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if userID == friendUserID {
		return false, xerr.New(xerr.InvalidArgument, "cannot delete self friend")
	}
	if s.userRepository == nil {
		return false, xerr.New(xerr.Unavailable, "user repository is not configured")
	}
	return s.userRepository.DeleteFriend(ctx, userID, friendUserID, s.now().UnixMilli())
}

func (s *Service) ListFriends(ctx context.Context, userID int64, page int32, pageSize int32, cursorUpdatedAtMS int64, cursorUserID int64) ([]userdomain.FriendRecord, int64, error) {
	if userID <= 0 {
		return nil, 0, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if s.userRepository == nil {
		return nil, 0, xerr.New(xerr.Unavailable, "user repository is not configured")
	}
	page, pageSize = normalizeSocialPage(page, pageSize)
	return s.userRepository.ListFriends(ctx, userID, page, pageSize, cursorUpdatedAtMS, cursorUserID)
}

func (s *Service) ListFriendApplications(ctx context.Context, userID int64, direction string, page int32, pageSize int32) ([]userdomain.FriendApplication, int64, error) {
	if userID <= 0 {
		return nil, 0, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	direction = strings.ToLower(strings.TrimSpace(direction))
	if direction == "" {
		direction = "incoming"
	}
	if direction != "incoming" && direction != "outgoing" {
		return nil, 0, xerr.New(xerr.InvalidArgument, "direction is invalid")
	}
	if s.userRepository == nil {
		return nil, 0, xerr.New(xerr.Unavailable, "user repository is not configured")
	}
	page, pageSize = normalizeSocialPage(page, pageSize)
	return s.userRepository.ListFriendApplications(ctx, userID, direction, page, pageSize)
}

func normalizeSocialPage(page int32, pageSize int32) (int32, int32) {
	if page <= 0 {
		page = 1
	}
	if pageSize <= 0 {
		pageSize = defaultSocialPageSize
	}
	if pageSize > maxSocialPageSize {
		pageSize = maxSocialPageSize
	}
	return page, pageSize
}
