// Package billing turns verified Paddle webhooks into licence actions. It never
// verifies signatures (that is paddle.VerifySignature at the edge) and never
// signs (that is licensing.Issue); it decides what a subscription's current
// state means and calls the issuer.
package billing

import (
	"context"
	"encoding/json"
	"fmt"
	"time"
)

// Event is the decoded Paddle webhook envelope. Data is left raw so each handler
// decodes only the shape it needs.
type Event struct {
	EventID    string          `json:"event_id"`
	EventType  string          `json:"event_type"`
	OccurredAt time.Time       `json:"occurred_at"`
	Data       json.RawMessage `json:"data"`
}

// Dispatch routes one event to its handler. Unknown event types are a no-op
// success: Paddle sends many we do not care about, and 200 stops it retrying.
func Dispatch(ctx context.Context, ev Event) error {
	switch ev.EventType {
	case "subscription.created", "subscription.updated", "subscription.activated":
		return handleSubscription(ctx, ev)
	case "subscription.canceled":
		return handleCanceled(ctx, ev)
	case "subscription.past_due":
		return handlePastDue(ctx, ev)
	case "transaction.completed":
		return handleTransactionCompleted(ctx, ev)
	case "transaction.payment_failed":
		return handlePaymentFailed(ctx, ev)
	case "customer.updated":
		return handleCustomerUpdated(ctx, ev)
	default:
		return nil
	}
}

// decode is a small helper so every handler decodes Data the same way.
func decode[T any](ev Event) (T, error) {
	var v T
	if err := json.Unmarshal(ev.Data, &v); err != nil {
		return v, fmt.Errorf("decode %s: %w", ev.EventType, err)
	}
	return v, nil
}
