2026-06-15 12:24:47 +00:00
package generatedtext
import (
"fmt"
"gitea.maximumdirect.net/eric/weatherreporter/internal/briefing"
"gitea.maximumdirect.net/eric/weatherreporter/internal/facts"
"gitea.maximumdirect.net/eric/weatherreporter/internal/module"
2026-07-31 03:53:47 +00:00
"gitea.maximumdirect.net/eric/weatherreporter/internal/promptassets"
2026-06-15 12:24:47 +00:00
"gitea.maximumdirect.net/eric/weatherreporter/internal/report"
"gitea.maximumdirect.net/eric/weatherreporter/internal/reporttemplate"
)
const (
schemaIDHourly = "hourly"
2026-06-15 16:23:13 +00:00
schemaIDDaily = "daily"
2026-06-15 14:45:49 +00:00
schemaIDToday = "today"
2026-06-15 12:24:47 +00:00
schemaIDTomorrow = "tomorrow"
templateIDHourly = "hourly"
2026-06-15 16:23:13 +00:00
templateIDDaily = "daily"
2026-06-15 14:45:49 +00:00
templateIDToday = "today"
2026-06-15 12:24:47 +00:00
templateIDTomorrow = "tomorrow"
)
2026-08-13 04:10:45 +00:00
type validator func ( [ ] byte ) ( any , error )
2026-06-15 12:24:47 +00:00
2026-08-13 02:11:25 +00:00
type renderContextBuilder func ( report . ID , string , briefing . PreparedIdentity , module . Snapshot , facts . DerivedFacts , any ) ( any , error )
2026-06-15 12:24:47 +00:00
type catalogEntry struct {
2026-08-13 01:36:56 +00:00
reportID report . ID
2026-06-15 12:52:18 +00:00
schemaID string
templateID string
validate validator
renderContextBuilder renderContextBuilder
2026-06-15 12:24:47 +00:00
}
type Handler struct {
2026-06-15 12:52:18 +00:00
reportID report . ID
schemaID string
templateID string
validate validator
renderContextBuilder renderContextBuilder
2026-06-15 12:24:47 +00:00
}
var catalog = [ ] catalogEntry {
{
2026-08-13 01:36:56 +00:00
reportID : report . Hourly ,
2026-06-15 12:52:18 +00:00
schemaID : schemaIDHourly ,
templateID : templateIDHourly ,
validate : validateHourly ,
renderContextBuilder : buildHourlyContext ,
2026-06-15 12:24:47 +00:00
} ,
2026-06-15 16:23:13 +00:00
{
2026-08-13 01:36:56 +00:00
reportID : report . Daily ,
2026-06-15 16:29:18 +00:00
schemaID : schemaIDDaily ,
templateID : templateIDDaily ,
validate : validateDaily ,
renderContextBuilder : buildDailyContext ,
2026-06-15 16:23:13 +00:00
} ,
2026-06-15 14:45:49 +00:00
{
2026-08-13 01:36:56 +00:00
reportID : report . Today ,
2026-06-15 14:45:49 +00:00
schemaID : schemaIDToday ,
templateID : templateIDToday ,
validate : validateToday ,
renderContextBuilder : buildTodayContext ,
} ,
2026-06-15 12:24:47 +00:00
{
2026-08-13 01:36:56 +00:00
reportID : report . Tomorrow ,
2026-06-15 12:52:18 +00:00
schemaID : schemaIDTomorrow ,
templateID : templateIDTomorrow ,
validate : validateTomorrow ,
renderContextBuilder : buildTomorrowContext ,
2026-06-15 12:24:47 +00:00
} ,
}
func LookupDefinition ( definition report . Definition ) ( Handler , error ) {
2026-08-13 01:36:56 +00:00
var schemaKnown , templateKnown , pairKnown bool
2026-06-15 12:24:47 +00:00
for _ , entry := range catalog {
if entry . schemaID == definition . GeneratedTextSchemaID {
schemaKnown = true
}
if entry . templateID == definition . TemplateID {
templateKnown = true
}
if entry . schemaID == definition . GeneratedTextSchemaID && entry . templateID == definition . TemplateID {
2026-08-13 01:36:56 +00:00
pairKnown = true
if entry . reportID != definition . ID {
continue
}
2026-06-15 12:24:47 +00:00
return Handler {
2026-08-13 01:36:56 +00:00
reportID : entry . reportID ,
2026-06-15 12:52:18 +00:00
schemaID : entry . schemaID ,
templateID : entry . templateID ,
validate : entry . validate ,
renderContextBuilder : entry . renderContextBuilder ,
2026-06-15 12:24:47 +00:00
} , nil
}
}
if ! schemaKnown {
return Handler { } , fmt . Errorf ( "generated text schema %q is not supported for report %q" , definition . GeneratedTextSchemaID , definition . ID )
}
if ! templateKnown {
return Handler { } , fmt . Errorf ( "report template %q is not supported for report %q" , definition . TemplateID , definition . ID )
}
2026-08-13 01:36:56 +00:00
if pairKnown {
return Handler { } , fmt . Errorf ( "generated text schema %q and report template %q do not belong to report %q" , definition . GeneratedTextSchemaID , definition . TemplateID , definition . ID )
}
2026-06-15 12:24:47 +00:00
return Handler { } , fmt . Errorf ( "generated text schema %q and report template %q are not supported together for report %q" , definition . GeneratedTextSchemaID , definition . TemplateID , definition . ID )
}
func ( h Handler ) SchemaID ( ) string {
return h . schemaID
}
func ( h Handler ) TemplateID ( ) string {
return h . templateID
}
func ( h Handler ) Schema ( ) ( [ ] byte , error ) {
2026-07-31 03:53:47 +00:00
data , err := promptassets . Schema ( h . schemaID )
2026-06-15 12:24:47 +00:00
if err != nil {
return nil , fmt . Errorf ( "load generated text schema %q for report %q: %w" , h . schemaID , h . reportID , err )
}
return data , nil
}
func ( h Handler ) Template ( ) ( string , error ) {
source , err := reporttemplate . Template ( h . templateID )
if err != nil {
return "" , fmt . Errorf ( "load report template %q for report %q: %w" , h . templateID , h . reportID , err )
}
return source , nil
}
2026-08-13 04:10:45 +00:00
func ( h Handler ) Validate ( data [ ] byte ) ( any , error ) {
2026-06-15 12:24:47 +00:00
if h . validate == nil {
2026-08-13 04:10:45 +00:00
return nil , fmt . Errorf ( "generated text validator is not registered for schema %q on report %q" , h . schemaID , h . reportID )
2026-06-15 12:24:47 +00:00
}
return h . validate ( data )
}
2026-08-13 02:11:25 +00:00
func ( h Handler ) BuildRenderContext ( identity briefing . PreparedIdentity , snapshot module . Snapshot , derived facts . DerivedFacts , generated any ) ( any , error ) {
2026-06-15 12:52:18 +00:00
if h . renderContextBuilder == nil {
2026-06-15 12:24:47 +00:00
return nil , fmt . Errorf ( "render-context builder is not registered for template %q on report %q" , h . templateID , h . reportID )
}
2026-08-13 02:11:25 +00:00
return h . renderContextBuilder ( h . reportID , h . templateID , identity , snapshot , derived , generated )
2026-06-15 12:24:47 +00:00
}
func ( h Handler ) Render ( data any ) ( [ ] byte , error ) {
rendered , err := reporttemplate . Render ( h . templateID , data )
if err != nil {
return nil , fmt . Errorf ( "render report template %q for report %q: %w" , h . templateID , h . reportID , err )
}
return rendered , nil
}
2026-08-13 04:10:45 +00:00
func validateHourly ( data [ ] byte ) ( any , error ) {
2026-06-15 12:24:47 +00:00
return ValidateHourly ( data )
}
2026-08-13 04:10:45 +00:00
func validateDaily ( data [ ] byte ) ( any , error ) {
2026-06-15 16:23:13 +00:00
return ValidateDaily ( data )
}
2026-08-13 04:10:45 +00:00
func validateToday ( data [ ] byte ) ( any , error ) {
2026-06-15 14:45:49 +00:00
return ValidateToday ( data )
}
2026-08-13 04:10:45 +00:00
func validateTomorrow ( data [ ] byte ) ( any , error ) {
2026-06-15 12:24:47 +00:00
return ValidateTomorrow ( data )
}
2026-08-13 02:11:25 +00:00
func buildHourlyContext ( reportID report . ID , templateID string , identity briefing . PreparedIdentity , snapshot module . Snapshot , _ facts . DerivedFacts , generated any ) ( any , error ) {
2026-06-15 12:24:47 +00:00
hourly , ok := generated . ( Hourly )
if ! ok {
return nil , fmt . Errorf ( "report template %q requires hourly generated text for report %q" , templateID , reportID )
}
2026-08-13 02:11:25 +00:00
return BuildHourlyRenderContext ( identity , snapshot , hourly )
2026-06-15 12:24:47 +00:00
}
2026-08-13 02:11:25 +00:00
func buildDailyContext ( reportID report . ID , templateID string , identity briefing . PreparedIdentity , snapshot module . Snapshot , derived facts . DerivedFacts , generated any ) ( any , error ) {
2026-06-15 16:29:18 +00:00
daily , ok := generated . ( Daily )
if ! ok {
return nil , fmt . Errorf ( "report template %q requires daily generated text for report %q" , templateID , reportID )
}
2026-08-13 02:11:25 +00:00
return BuildDailyRenderContext ( identity , snapshot , daily , derived )
2026-06-15 16:29:18 +00:00
}
2026-08-13 02:11:25 +00:00
func buildTodayContext ( reportID report . ID , templateID string , identity briefing . PreparedIdentity , snapshot module . Snapshot , derived facts . DerivedFacts , generated any ) ( any , error ) {
2026-06-15 14:45:49 +00:00
today , ok := generated . ( Today )
if ! ok {
return nil , fmt . Errorf ( "report template %q requires today generated text for report %q" , templateID , reportID )
}
2026-08-13 02:11:25 +00:00
return BuildTodayRenderContext ( identity , snapshot , today , derived )
2026-06-15 14:45:49 +00:00
}
2026-08-13 02:11:25 +00:00
func buildTomorrowContext ( reportID report . ID , templateID string , identity briefing . PreparedIdentity , snapshot module . Snapshot , derived facts . DerivedFacts , generated any ) ( any , error ) {
2026-06-15 12:24:47 +00:00
tomorrow , ok := generated . ( Tomorrow )
if ! ok {
return nil , fmt . Errorf ( "report template %q requires tomorrow generated text for report %q" , templateID , reportID )
}
2026-08-13 02:11:25 +00:00
return BuildTomorrowRenderContext ( identity , snapshot , tomorrow , derived )
2026-06-15 12:24:47 +00:00
}