package services

// Variable resolvers — the paliad-side implementations of
// docforge.VariableResolver (t-paliad-349 slice 3). Each wraps one of the
// addXxxVars push-builders, capturing the entity it needs, so the proven
// builder bodies stay byte-for-byte unchanged while the composition moves
// behind the docforge.ResolverSet seam. SubmissionVarsService.Build wires
// the applicable resolvers and calls ResolverSet.BuildBag().
//
// These live in paliad (not docforge) because they read paliad's domain
// model — branding, user, project, parties, deadline_rules, deadlines. A
// second docforge consumer implements its own resolvers against its own
// data and plugs them into a ResolverSet the same way.

import (
	"time"

	"mgit.msbls.de/m/paliad/internal/models"
	"mgit.msbls.de/m/paliad/pkg/docforge"
)

// Compile-time conformance: each resolver satisfies docforge.VariableResolver.
var (
	_ docforge.VariableResolver = firmResolver{}
	_ docforge.VariableResolver = todayResolver{}
	_ docforge.VariableResolver = userResolver{}
	_ docforge.VariableResolver = proceduralEventResolver{}
	_ docforge.VariableResolver = projectResolver{}
	_ docforge.VariableResolver = partiesResolver{}
	_ docforge.VariableResolver = deadlineResolver{}
)

// firmResolver populates firm.* from process-wide branding.
type firmResolver struct{}

func (firmResolver) Namespace() string           { return "firm" }
func (firmResolver) Populate(bag PlaceholderMap) { addFirmVars(bag) }

// todayResolver populates today.* from the build-time clock.
type todayResolver struct{ now time.Time }

func (todayResolver) Namespace() string             { return "today" }
func (r todayResolver) Populate(bag PlaceholderMap) { addTodayVars(bag, r.now) }

// userResolver populates user.* from the caller's row.
type userResolver struct{ user *models.User }

func (userResolver) Namespace() string             { return "user" }
func (r userResolver) Populate(bag PlaceholderMap) { addUserVars(bag, r.user) }

// proceduralEventResolver populates procedural_event.* and the legacy
// rule.* alias from the published deadline_rule.
type proceduralEventResolver struct {
	rule *models.DeadlineRule
	lang string
}

func (proceduralEventResolver) Namespace() string             { return "procedural_event" }
func (r proceduralEventResolver) Populate(bag PlaceholderMap) { addRuleVars(bag, r.rule, r.lang) }

// projectResolver populates project.* from the project + its proceeding type.
type projectResolver struct {
	project *models.Project
	pt      *models.ProceedingType
	lang    string
}

func (projectResolver) Namespace() string             { return "project" }
func (r projectResolver) Populate(bag PlaceholderMap) { addProjectVars(bag, r.project, r.pt, r.lang) }

// partiesResolver populates parties.* from the (already filtered) party list.
type partiesResolver struct{ parties []models.Party }

func (partiesResolver) Namespace() string             { return "parties" }
func (r partiesResolver) Populate(bag PlaceholderMap) { addPartyVars(bag, r.parties) }

// deadlineResolver populates deadline.* from the next pending deadline.
type deadlineResolver struct {
	deadline *models.Deadline
	project  *models.Project
	lang     string
}

func (deadlineResolver) Namespace() string { return "deadline" }
func (r deadlineResolver) Populate(bag PlaceholderMap) {
	addDeadlineVars(bag, r.deadline, r.project, r.lang)
}
