// Package upc provides an embedded, DB-free implementation of the
// litigationplanner Catalog / HolidayCalendar / CourtRegistry
// interfaces, populated from a JSON snapshot of paliad's UPC rule
// corpus.
//
// Slice C of the litigation-planner extraction (m/paliad#124 §19).
//
// Consumers (today: youpc.org; future: any third-party UPC tool) wire
// the engine like this:
//
//	import (
//	    lp "mgit.msbls.de/m/paliad/pkg/litigationplanner"
//	    upc "mgit.msbls.de/m/paliad/pkg/litigationplanner/embedded/upc"
//	)
//
//	cat, _ := upc.NewCatalog()
//	hc, _  := upc.NewHolidayCalendar()
//	cr, _  := upc.NewCourtRegistry()
//
//	timeline, err := lp.Calculate(ctx, "upc.inf.cfi", "2026-05-26",
//	    lp.CalcOptions{}, cat, hc, cr)
//
// Regenerating the snapshot: see cmd/gen-upc-snapshot/README.md.
//
//go:generate sh -c "echo 'snapshot is regenerated via the gen-upc-snapshot binary — see cmd/gen-upc-snapshot/README.md'"
package upc

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

// rawFS holds the snapshot JSON files. The data files are produced by
// cmd/gen-upc-snapshot from a paliad live DB.
//
//go:embed *.json
var rawFS embed.FS

// Meta is the version block from meta.json.
type Meta struct {
	Version           string    `json:"version"`
	GeneratedAt       time.Time `json:"generated_at"`
	PaliadCommit      string    `json:"paliad_commit,omitempty"`
	SourceDBLabel     string    `json:"source_db_label,omitempty"`
	RuleCount         int       `json:"rule_count"`
	ProceedingCount   int       `json:"proceeding_count"`
	TriggerEventCount int       `json:"trigger_event_count"`
	HolidayCount      int       `json:"holiday_count"`
	CourtCount        int       `json:"court_count"`
}

// LoadMeta parses meta.json from the embedded snapshot. Returns an
// error when the snapshot hasn't been generated yet (meta.json
// missing or empty).
func LoadMeta() (Meta, error) {
	var m Meta
	buf, err := rawFS.ReadFile("meta.json")
	if err != nil {
		return Meta{}, fmt.Errorf("read meta.json: %w", err)
	}
	if err := json.Unmarshal(buf, &m); err != nil {
		return Meta{}, fmt.Errorf("decode meta.json: %w", err)
	}
	return m, nil
}

// readJSON is a tiny helper that decodes one of the embedded files
// into a destination value.
func readJSON(name string, dst any) error {
	buf, err := rawFS.ReadFile(name)
	if err != nil {
		return fmt.Errorf("read %s: %w", name, err)
	}
	if err := json.Unmarshal(buf, dst); err != nil {
		return fmt.Errorf("decode %s: %w", name, err)
	}
	return nil
}
