// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package federation

import (
	"context"

	activities_model "forgejo.org/models/activities"
	"forgejo.org/models/forgefed"
	"forgejo.org/models/user"
	"forgejo.org/modules/setting"
	"forgejo.org/modules/structs"
	"forgejo.org/services/convert"

	ap "github.com/go-ap/activitypub"
	"github.com/go-ap/jsonld"
)

func SendUserActivity(ctx context.Context, doer *user.User, activity *activities_model.Action) error {
	followers, err := user.GetFollowersForUser(ctx, doer)
	if err != nil {
		return err
	}

	userActivity, err := convert.ActionToForgeUserActivity(ctx, activity)
	if err != nil {
		return err
	}

	payload, err := jsonld.WithContext(
		jsonld.IRI(ap.ActivityBaseURI),
	).Marshal(userActivity)
	if err != nil {
		return err
	}

	for _, follower := range followers {
		_, federatedUserFollower, err := user.GetFederatedUserByUserID(ctx, follower.FollowingUserID)
		if err != nil {
			return err
		}

		federationHost, err := forgefed.GetFederationHost(ctx, federatedUserFollower.FederationHostID)
		if err != nil {
			return err
		}

		hostURL := federationHost.AsURL()
		if err := deliveryQueue.Push(deliveryQueueItem{
			InboxURL: hostURL.JoinPath(federatedUserFollower.InboxPath).String(),
			Doer:     doer,
			Payload:  payload,
		}); err != nil {
			return err
		}
	}

	return nil
}

func NotifyActivityPubFollowers(ctx context.Context, actions []activities_model.Action) error {
	if !setting.Federation.Enabled {
		return nil
	}
	for _, act := range actions {
		if act.Repo != nil {
			if act.Repo.IsPrivate {
				continue
			}
			if act.Repo.Owner.KeepActivityPrivate || act.Repo.Owner.Visibility != structs.VisibleTypePublic {
				continue
			}
		}
		if act.ActUser.KeepActivityPrivate || act.ActUser.Visibility != structs.VisibleTypePublic {
			continue
		}
		if err := SendUserActivity(ctx, act.ActUser, &act); err != nil {
			return err
		}
	}
	return nil
}
