package federation

import (
	"fmt"
	"os"
	"path"
	"pocketbase/util"
	"time"

	pub "github.com/go-ap/activitypub"
	"github.com/pocketbase/pocketbase/core"
	"github.com/pocketbase/pocketbase/tools/security"
)

// create outgoing follow activity
func CreateLikeActivity(app core.App, like *core.Record) error {
	origin := os.Getenv("ORIGIN")
	if origin == "" {
		return fmt.Errorf("ORIGIN not set")
	}

	actor, err := app.FindRecordById("activitypub_actors", like.GetString("actor"))
	if err != nil {
		return err
	}

	trail, err := app.FindRecordById("trails", like.GetString("trail"))
	if err != nil {
		return err
	}

	trailAuthor, err := app.FindRecordById("activitypub_actors", trail.GetString("author"))
	if err != nil {
		return err
	}

	object := trail.GetString("iri")

	if object == "" {
		// trail is local
		object = fmt.Sprintf("%s/api/v1/trail/%s", origin, trail.Id)
	}

	collection, err := app.FindCollectionByNameOrId("activitypub_activities")
	if err != nil {
		return err
	}

	recordId := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)

	id := fmt.Sprintf("%s/api/v1/activitypub/activity/%s", origin, recordId)

	activity := pub.LikeNew(pub.IRI(id), pub.IRI(object))
	activity.Actor = pub.IRI(actor.GetString("iri"))

	err = PostActivity(app, actor, activity, []string{trailAuthor.GetString("inbox")})
	if err != nil {
		return err
	}

	record := core.NewRecord(collection)
	record.Set("id", recordId)
	record.Set("iri", id)
	record.Set("type", string(pub.LikeType))
	record.Set("object", object)
	record.Set("actor", actor.GetString("iri"))
	record.Set("published", time.Now())

	return app.Save(record)
}

// process incoming like activity
func ProcessLikeActivity(app core.App, actor *core.Record, activity pub.Activity) error {
	origin := os.Getenv("ORIGIN")
	if origin == "" {
		return fmt.Errorf("ORIGIN not set")
	}

	trailId := path.Base(activity.Object.GetID().String())
	trail, err := app.FindRecordById("trails", trailId)
	if err != nil {
		return err
	}

	trailAuthor, err := app.FindRecordById("activitypub_actors", trail.GetString("author"))
	if err != nil {
		return err
	}

	if !actor.GetBool("isLocal") {
		trailLikeCollection, err := app.FindCollectionByNameOrId("trail_like")
		if err != nil {
			return err
		}
		likeRecord := core.NewRecord(trailLikeCollection)
		likeRecord.Set("trail", trail.Id)
		likeRecord.Set("actor", actor.Id)
		err = app.Save(likeRecord)
		if err != nil {
			return err
		}
	}

	// send a notification to the trail author
	notification := util.Notification{
		Type: util.TrailLike,
		Metadata: map[string]string{
			"trail_id":     trail.Id,
			"trail_name":   trail.GetString("name"),
			"trail_author": fmt.Sprintf("@%s", trailAuthor.GetString("preferred_username")),
			"liker":        fmt.Sprintf("@%s@%s", actor.GetString("preferred_username"), actor.GetString("domain")),
		},
		Seen:   false,
		Author: actor.Id,
	}
	return util.SendNotification(app, notification, trailAuthor)

}
