package webhooks

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

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

// QbitHandler parses the body produced by the operator-installed shell
// template (scripts/qbit-hook-template.sh) and publishes typed completion /
// state-change events on the bus.
//
// The shell template POSTs a JSON envelope shaped like qbitPayload below.
// Operators can extend the template to add fields; unrecognized fields are
// ignored.
type QbitHandler struct {
	Bus *eventbus.Bus
}

func (h *QbitHandler) HandlerType() string { return "qbit" }

type qbitPayload struct {
	Kind     string `json:"kind"` // "completed" | "state_changed" | "tracker_changed"
	Hash     string `json:"info_hash"`
	Name     string `json:"name"`
	State    string `json:"state"`
	Category string `json:"category"`
	Tags     string `json:"tags"`
	SavePath string `json:"save_path"`
	Tracker  string `json:"tracker"`
}

func (h *QbitHandler) Handle(ctx context.Context, r *http.Request, body []byte, endpointID string) error {
	var p qbitPayload
	if err := json.Unmarshal(body, &p); err != nil {
		return err
	}
	if p.Kind == "" {
		p.Kind = "completed" // historical default for the operator hook
	}
	ev := QbitEvent{
		Kind:       p.Kind,
		InfoHash:   p.Hash,
		Name:       p.Name,
		State:      p.State,
		Category:   p.Category,
		Tags:       p.Tags,
		SavePath:   p.SavePath,
		Tracker:    p.Tracker,
		ReceivedAt: time.Now(),
		EndpointID: endpointID,
	}
	if h.Bus == nil {
		return nil
	}
	// Publish on the kind-specific topic AND on TopicTorrents so existing
	// Phase 3 subscribers see the event without changing their topic.
	switch p.Kind {
	case "completed":
		h.Bus.Publish(eventbus.Event{Topic: eventbus.TopicTorrentCompleted, Payload: ev})
	case "tracker_changed":
		h.Bus.Publish(eventbus.Event{Topic: eventbus.TopicTrackerStatusChanged, Payload: ev})
	default:
		h.Bus.Publish(eventbus.Event{Topic: eventbus.TopicTorrentStateChanged, Payload: ev})
	}
	h.Bus.Publish(eventbus.Event{Topic: eventbus.TopicTorrents, Payload: ev})
	return nil
}
