package catalog

import (
	"context"
	"log"
	"sync"
	"time"

	"cloud.google.com/go/firestore"
)

const bucketBaseURL = "https://storage.googleapis.com/reimage-assets"
const cacheTTL = 5 * time.Minute

// Product is the Firestore schema for catalog entries. The Python admin
// tool that seeds this collection lives at github.com/reimage-ai/catalog-admin
// (catalog.py mirrors this struct — keep both in sync).
type Product struct {
	ID           string   `json:"id"                     firestore:"-"`
	Name         string   `json:"name"                   firestore:"name"`
	SimpleName   string   `json:"simple_name"            firestore:"simple_name"`
	Category     string   `json:"category"               firestore:"category"`
	Rooms        []string `json:"rooms"                  firestore:"rooms"`
	WidthMeters  float64  `json:"width_meters,omitempty" firestore:"width_meters,omitempty"`
	ThumbnailURL string   `json:"thumbnail_url"          firestore:"-"`
	ImageURL     string   `json:"image_url"              firestore:"-"`
	StickerURL   string   `json:"sticker_url,omitempty"  firestore:"-"`
	HasGlb       bool     `json:"has_glb"                firestore:"has_glb"`
	SortOrder    int      `json:"sort_order"             firestore:"sort_order"`

	// Firestore-only fields — not serialized in JSON response.
	// GLB path is intentionally excluded from the response; clients derive
	// the GLB URL on demand via convention: {bucketBaseURL}/catalog/{id}/model.glb
	ThumbnailPath string `json:"-" firestore:"thumbnail_path"`
	ImagePath     string `json:"-" firestore:"image_path"`
	StickerPath   string `json:"-" firestore:"sticker_path,omitempty"`
	GlbPath       string `json:"-" firestore:"glb_path,omitempty"`
	Active        bool   `json:"-" firestore:"active"`
}

var (
	cache     []Product
	cacheTime time.Time
	cacheMu   sync.RWMutex
)

// GetCatalog returns active products with thumbnail and image URLs.
// GLB URLs are NOT included — lightweight catalog only.
// Clients derive the GLB URL from convention when a product is added to the tray.
// Returns (nil, error) only on first-ever fetch failure (no stale cache available).
func GetCatalog(client *firestore.Client) ([]Product, error) {
	cacheMu.RLock()
	if cache != nil && time.Since(cacheTime) < cacheTTL {
		result := cache
		cacheMu.RUnlock()
		return result, nil
	}
	cacheMu.RUnlock()

	ctx := context.Background()
	docs, err := client.Collection("catalog").
		Where("active", "==", true).
		Documents(ctx).GetAll()
	if err != nil {
		// Stale-on-error: return expired cache if available rather than surfacing a 5xx
		cacheMu.RLock()
		stale := cache
		cacheMu.RUnlock()
		if stale != nil {
			log.Printf("Warning: Catalog: Firestore error, serving stale cache: %v\n", err)
			return stale, nil
		}
		return nil, err
	}

	products := make([]Product, 0, len(docs))
	for _, doc := range docs {
		var p Product
		if err := doc.DataTo(&p); err != nil {
			log.Printf("Error: Catalog: skip bad doc %s: %v\n", doc.Ref.ID, err)
			continue
		}
		p.ID = doc.Ref.ID
		p.ThumbnailURL = bucketBaseURL + "/" + p.ThumbnailPath
		p.ImageURL = bucketBaseURL + "/" + p.ImagePath
		if p.StickerPath != "" {
			p.StickerURL = bucketBaseURL + "/" + p.StickerPath
		}
		products = append(products, p)
	}

	cacheMu.Lock()
	cache = products
	cacheTime = time.Now()
	cacheMu.Unlock()

	return products, nil
}
