package webhooks

import (
	"context"
	"encoding/json"
	"net/http"
	"time"

	"github.com/operator/command-center/internal/eventbus"
)

// AutobrrHandler parses autobrr's webhook body and publishes
// TopicAutobrrGrab.
//
// autobrr lets the operator define the webhook body template, so the shape
// the Command Center receives is whatever the operator configured. This
// handler accepts a generous superset of common field names and pulls out
// what it recognizes; unknown fields are preserved in the audit log via
// the system_events table (Phase 0 EventRecorder).
type AutobrrHandler struct {
	Bus *eventbus.Bus
}

// HandlerType returns the type string.
func (h *AutobrrHandler) HandlerType() string { return "autobrr" }

// autobrrPayload models the fields commonly available in autobrr's
// {{ .Foo }} macro set. Operators configuring their autobrr filter's
// webhook action template should produce a JSON body shaped like this.
type autobrrPayload struct {
	EventID     string `json:"event_id"`
	FilterID    string `json:"filter_id"`
	FilterName  string `json:"filter_name"`
	ReleaseName string `json:"release_name"`
	Name        string `json:"name"` // some templates use "name" for release
	Indexer     string `json:"indexer"`
	InfoHash    string `json:"info_hash"`
	TorrentHash string `json:"torrent_hash"`
	Hash        string `json:"hash"`
	Size        int64  `json:"size"`
	Timestamp   string `json:"timestamp"`
}

// Handle parses the body and publishes the typed event.
func (h *AutobrrHandler) Handle(ctx context.Context, r *http.Request, body []byte, endpointID string) error {
	var p autobrrPayload
	if err := json.Unmarshal(body, &p); err != nil {
		return err
	}
	releaseName := p.ReleaseName
	if releaseName == "" {
		releaseName = p.Name
	}
	hash := firstNonEmpty(p.InfoHash, p.TorrentHash, p.Hash)
	grabbedAt := time.Now()
	if p.Timestamp != "" {
		if t, err := time.Parse(time.RFC3339, p.Timestamp); err == nil {
			grabbedAt = t
		}
	}

	if h.Bus != nil {
		h.Bus.Publish(eventbus.Event{
			Topic: eventbus.TopicAutobrrGrab,
			Payload: AutobrrGrabEvent{
				EventID:     p.EventID,
				FilterID:    p.FilterID,
				FilterName:  p.FilterName,
				ReleaseName: releaseName,
				Indexer:     p.Indexer,
				InfoHash:    hash,
				Size:        p.Size,
				GrabbedAt:   grabbedAt,
				ReceivedAt:  time.Now(),
				EndpointID:  endpointID,
			},
		})
	}
	return nil
}

func firstNonEmpty(ss ...string) string {
	for _, s := range ss {
		if s != "" {
			return s
		}
	}
	return ""
}
