package blossom

import (
	"context"
	"iter"
	"strconv"

	"fiatjaf.com/nostr"
	"fiatjaf.com/nostr/eventstore"
)

// EventStoreBlobIndexWrapper uses fake events to keep track of what blobs we have stored and who owns them
type EventStoreBlobIndexWrapper struct {
	eventstore.Store

	ServiceURL string
}

func (es EventStoreBlobIndexWrapper) Keep(ctx context.Context, blob BlobDescriptor, pubkey nostr.PubKey) error {
	next, stop := iter.Pull(
		es.Store.QueryEvents(nostr.Filter{Authors: []nostr.PubKey{pubkey}, Kinds: []nostr.Kind{24242}, Tags: nostr.TagMap{"x": []string{blob.SHA256}}}, 1),
	)
	defer stop()

	if _, exists := next(); !exists {
		// doesn't exist, save
		evt := nostr.Event{
			PubKey: pubkey,
			Kind:   24242,
			Tags: nostr.Tags{
				{"x", blob.SHA256},
				{"type", blob.Type},
				{"size", strconv.Itoa(blob.Size)},
			},
			CreatedAt: blob.Uploaded,
		}
		evt.ID = evt.GetID()
		es.Store.SaveEvent(evt)
	}

	return nil
}

func (es EventStoreBlobIndexWrapper) List(ctx context.Context, pubkey nostr.PubKey) iter.Seq[BlobDescriptor] {
	return func(yield func(BlobDescriptor) bool) {
		for evt := range es.Store.QueryEvents(nostr.Filter{
			Authors: []nostr.PubKey{pubkey},
			Kinds:   []nostr.Kind{24242},
		}, 1000) {
			yield(es.parseEvent(evt))
		}
	}
}

func (es EventStoreBlobIndexWrapper) Get(ctx context.Context, sha256 string) (*BlobDescriptor, error) {
	next, stop := iter.Pull(
		es.Store.QueryEvents(nostr.Filter{Tags: nostr.TagMap{"x": []string{sha256}}, Kinds: []nostr.Kind{24242}, Limit: 1}, 1),
	)

	defer stop()

	if evt, found := next(); found {
		bd := es.parseEvent(evt)
		return &bd, nil
	}

	return nil, nil
}

func (es EventStoreBlobIndexWrapper) Delete(ctx context.Context, sha256 string, pubkey nostr.PubKey) error {
	next, stop := iter.Pull(
		es.Store.QueryEvents(nostr.Filter{
			Authors: []nostr.PubKey{pubkey},
			Tags:    nostr.TagMap{"x": []string{sha256}},
			Kinds:   []nostr.Kind{24242},
			Limit:   1,
		}, 1),
	)

	defer stop()

	if evt, found := next(); found {
		return es.Store.DeleteEvent(evt.ID)
	}

	return nil
}

func (es EventStoreBlobIndexWrapper) parseEvent(evt nostr.Event) BlobDescriptor {
	hhash := evt.Tags[0][1]
	mimetype := evt.Tags[1][1]
	ext := getExtension(mimetype)
	size, _ := strconv.Atoi(evt.Tags[2][1])

	return BlobDescriptor{
		Owner:    evt.PubKey,
		Uploaded: evt.CreatedAt,
		URL:      es.ServiceURL + "/" + hhash + ext,
		SHA256:   hhash,
		Type:     mimetype,
		Size:     size,
	}
}
