package blossom

import (
	"context"
	"io"
	"net/http"
	"net/url"
	"strings"

	"fiatjaf.com/nostr"
	"fiatjaf.com/nostr/khatru"
)

type BlossomServer struct {
	ServiceURL string
	Store      BlobIndex

	StoreBlob     func(ctx context.Context, sha256 string, ext string, body []byte) error
	LoadBlob      func(ctx context.Context, sha256 string, ext string) (io.ReadSeeker, *url.URL, error)
	DeleteBlob    func(ctx context.Context, sha256 string, ext string) error
	ReceiveReport func(ctx context.Context, reportEvt nostr.Event) error

	RejectUpload func(ctx context.Context, auth *nostr.Event, size int, ext string) (bool, string, int)
	RejectGet    func(ctx context.Context, auth *nostr.Event, sha256 string, ext string) (bool, string, int)
	RejectList   func(ctx context.Context, auth *nostr.Event, pubkey nostr.PubKey) (bool, string, int)
	RejectDelete func(ctx context.Context, auth *nostr.Event, sha256 string, ext string) (bool, string, int)
}

func New(rl *khatru.Relay, serviceURL string) *BlossomServer {
	bs := &BlossomServer{
		ServiceURL: serviceURL,
	}

	base := rl.Router()
	mux := http.NewServeMux()

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path == "/upload" {
			if r.Method == "PUT" {
				bs.handleUpload(w, r)
				return
			} else if r.Method == "HEAD" {
				bs.handleUploadCheck(w, r)
				return
			}
		}

		if r.URL.Path == "/media" {
			bs.handleMedia(w, r)
			return
		}
		if r.URL.Path == "/mirror" && r.Method == "PUT" {
			bs.handleMirror(w, r)
			return
		}

		if strings.HasPrefix(r.URL.Path, "/list/") && r.Method == "GET" {
			bs.handleList(w, r)
			return
		}

		if (len(r.URL.Path) == 65 || strings.Index(r.URL.Path, ".") == 65) && strings.Index(r.URL.Path[1:], "/") == -1 {
			if r.Method == "HEAD" {
				bs.handleHasBlob(w, r)
				return
			} else if r.Method == "GET" {
				bs.handleGetBlob(w, r)
				return
			} else if r.Method == "DELETE" {
				bs.handleDelete(w, r)
				return
			}
		}

		if r.URL.Path == "/report" {
			if r.Method == "PUT" {
				bs.handleReport(w, r)
				return
			}
		}

		base.ServeHTTP(w, r)
	})

	rl.SetRouter(mux)

	return bs
}
