package main

import (
	"encoding/json"

	module "bijection.dev/module"
	"bijection.dev/module/product"
	"github.com/rafflesia-ai/bijection/algebra"
	aa "github.com/rafflesia-ai/bijection/algebra/action"
	av "github.com/rafflesia-ai/bijection/algebra/value"
	workflow "github.com/rafflesia-ai/bijection/algebra/workflow"
)

const definitionModule = "onboarding_definition"

func must[T any](value T, err error) T {
	if err != nil {
		panic(err)
	}
	return value
}
func text(value string) av.Value { return must(av.String(value)) }
func column(name string, kind av.Type, nullable bool, labels ...string) av.Column {
	values := make([]av.Label, 0, len(labels))
	for _, label := range labels {
		values = append(values, must(av.NewLabel(label, "")))
	}
	return must(av.NewColumn(av.ColumnOptions{Name: name, Type: kind, Nullable: nullable, Labels: values}))
}
func property(name string, kind av.Type, nullable, writable bool, labels ...string) algebra.ObjectProperty {
	return must(algebra.NewObjectProperty(algebra.ObjectPropertyOptions{Column: column(name, kind, nullable, labels...), Type: algebra.ScalarPropertyType(kind), Writable: writable}))
}
func policy(value algebra.Predicate) module.Value { return *must(product.PolicyPredicate(value)) }
func read(root, name string, path ...string) product.ProgramRead {
	return product.ProgramRead{Root: root, Name: name, Path: path}
}
func permission(kind, name string, fields ...string) product.ProgramEffectPermission {
	return product.ProgramEffectPermission{Kind: kind, Name: name, Fields: fields}
}
func deferred(name string) []product.ProgramSelector {
	return []product.ProgramSelector{product.DeferredProgram(definitionModule, name, product.ProgramActionEffects)}
}

func init() {
	module.Register(product.DefinePrograms(module.Program{Construction: product.Define(define)}, map[string]func(module.Context, module.Value) (module.Value, error){
		product.ProgramActionEffects + ":register_supplier":          registerSupplier,
		product.ProgramActionEffects + ":record_evidence":            recordEvidence,
		product.ProgramActionEffects + ":request_onboarding":         requestOnboarding,
		product.ProgramActionEffects + ":record_findings":            recordFindings,
		product.ProgramActionEffects + ":approve_supplier":           approveSupplier,
		product.ProgramActionEffects + ":activate_supplier":          activateSupplier,
		product.ProgramActionEffects + ":record_supplier_risk":       recordSupplierRisk,
		product.ProgramActionEffects + ":record_investigation":       recordInvestigation,
		product.ProgramActionEffects + ":publish_imported_supplier":  publishImportedSupplier,
		product.ProgramActionEffects + ":request_signature":          requestSignature,
		product.ProgramActionEffects + ":send_signature_request":     sendSignatureRequest,
		product.ProgramActionEffects + ":confirm_signature_delivery": confirmSignatureDelivery,
		product.ProgramActionEffects + ":send_signature_reminder":    sendSignatureReminder,
		product.ProgramActionEffects + ":accept_signature":           acceptSignature,
		product.ProgramActionEffects + ":expire_signature":           expireSignature,
		product.ProgramActionEffects + ":cancel_signature":           cancelSignature,
		product.ProgramActionEffects + ":activate_signed_agreement":  activateSignedAgreement,
	}))
}
func main() {}

func define(module.Context, module.Value) (product.Document, error) {
	supplier := must(algebra.NewObjectDefinition(algebra.ObjectOptions{Name: "Supplier", Description: "A supplier and the exact evidence revision considered for activation.", PlatformBacked: true, Key: []string{"supplier_id"}, Properties: []algebra.ObjectProperty{
		property("supplier_id", av.TypeString, false, false), property("name", av.TypeString, false, false), property("is_active", av.TypeBoolean, false, true), property("evidence_revision", av.TypeInteger, false, true), property("evidence_complete", av.TypeBoolean, false, true), property("is_high_risk", av.TypeBoolean, false, true), property("risk_revision", av.TypeInteger, false, true),
	}, Display: algebra.ObjectDisplay{Primary: "name", Secondary: "supplier_id"}}))
	caseObject := must(algebra.NewObjectDefinition(algebra.ObjectOptions{Name: "OnboardingCase", Description: "Business record for onboarding, independent from any Workflow run.", PlatformBacked: true, Key: []string{"case_id"}, Properties: []algebra.ObjectProperty{
		property("case_id", av.TypeString, false, false), property("supplier_id", av.TypeString, false, false), property("status", av.TypeString, false, true, "requested", "needs_evidence", "awaiting_approval", "approved", "awaiting_signature", "signature_expired", "signature_cancelled", "complete"), property("evidence_revision", av.TypeInteger, false, true), property("approved_revision", av.TypeInteger, true, true), property("findings", av.TypeString, false, true),
	}, Display: algebra.ObjectDisplay{Primary: "case_id", Secondary: "status"}}))
	assessmentSchema := must(av.NewSchema([]av.Column{column("supplier_id", av.TypeString, false), column("evidence_revision", av.TypeInteger, false), column("evidence_complete", av.TypeBoolean, false), column("findings", av.TypeString, false), column("route", av.TypeString, false)}, nil, nil))
	assessmentBody := must(algebra.SQLRelation(algebra.SQLRelationOptions{Dialect: algebra.DialectPostgres, Text: `SELECT s.supplier_id, s.evidence_revision, s.evidence_complete, CASE WHEN s.evidence_complete THEN 'Evidence package is complete.' ELSE 'Required supplier evidence is incomplete.' END AS findings, CASE WHEN s.evidence_complete THEN 'awaiting_approval' ELSE 'needs_evidence' END AS route FROM "input.cases" c JOIN "input.suppliers" s ON s.supplier_id = c.supplier_id WHERE c.case_id = $1`, Inputs: []algebra.SQLInput{{Name: "cases", Relation: algebra.SourceRelation("OnboardingCase", "c")}, {Name: "suppliers", Relation: algebra.SourceRelation("Supplier", "s")}}, Arguments: []algebra.Expr{algebra.Param("case_id")}, Schema: assessmentSchema}))
	assessment := must(algebra.NewFunctionDefinition(algebra.FunctionOptions{Name: "assess_supplier", Parameters: []algebra.Parameter{must(algebra.NewParameterDefinition(algebra.ParameterOptions{Name: "case_id", Type: av.TypeString}))}, Cardinality: algebra.CardinalityOne, Body: assessmentBody, ResultKind: "onboarding.assessment", Doc: "Assess the current supplier evidence for an onboarding case."}))
	listSchema := must(av.NewSchema([]av.Column{column("case_id", av.TypeString, false), column("supplier_id", av.TypeString, false), column("status", av.TypeString, false), column("evidence_revision", av.TypeInteger, false), column("findings", av.TypeString, false)}, []av.Order{must(av.NewOrder("case_id", av.Ascending, av.NullsLast))}, nil))
	listBody := must(algebra.SQLRelation(algebra.SQLRelationOptions{Dialect: algebra.DialectPostgres, Text: `SELECT case_id, supplier_id, status, evidence_revision, findings FROM "input.cases" ORDER BY case_id`, Inputs: []algebra.SQLInput{{Name: "cases", Relation: algebra.SourceRelation("OnboardingCase", "c")}}, Schema: listSchema}))
	list := must(algebra.NewFunctionDefinition(algebra.FunctionOptions{Name: "onboarding_cases", Cardinality: algebra.CardinalityMany, Body: listBody, ResultKind: "onboarding.cases", Doc: "Current onboarding cases."}))
	functions := append(append([]algebra.FunctionDefinition{assessment, list, supplierRiskFunction()}, importerFunctions()...), signatureFunctions()...)
	definition := algebra.NewDefinition(nil, []algebra.ObjectDefinition{supplier, caseObject, riskCaseObject(), importedSupplierObject(), signatureRequestObject()}, signatureRelationships(), []algebra.PolicyDefinition{algebra.RowGuardPolicy("supplier_visible", "Supplier", algebra.True()), algebra.RowGuardPolicy("onboarding_case_visible", "OnboardingCase", algebra.True()), algebra.RowGuardPolicy("risk_case_visible", "SupplierRiskCase", algebra.True()), algebra.RowGuardPolicy("imported_supplier_visible", "ImportedSupplier", algebra.True()), algebra.RowGuardPolicy("signature_request_visible", "SignatureRequest", algebra.True())}, functions, nil)
	algebraValue, err := product.Algebra(definition)
	if err != nil {
		return product.Document{}, err
	}
	workflowValue, err := product.Algebra(workflowDefinition())
	if err != nil {
		return product.Document{}, err
	}
	yes, no := policy(algebra.True()), policy(algebra.False())
	actions := []product.Action{
		product.NewAction(product.Action{Name: "RegisterSupplier", Label: "Register supplier", Creates: "Supplier", KeyFrom: "supplier_id", Inputs: []product.ActionInput{{Name: "supplier_id", Type: "string"}, {Name: "name", Type: "string", MinimumLength: 1}}, Programs: deferred("register_supplier"), Ceiling: product.ProgramCeiling{Reads: []product.ProgramRead{read("input", "supplier_id"), read("input", "name")}, Dependencies: []string{"Supplier"}, Effects: []product.ProgramEffectPermission{permission("create_object", "Supplier", "name", "is_active", "evidence_revision", "evidence_complete", "is_high_risk", "risk_revision")}, MaxEffects: 1, MaxValueBytes: 8192}, AllowedFor: yes, AllowedIf: yes, RequiresReview: no}),
		product.NewAction(product.Action{Name: "RecordSupplierEvidence", Label: "Record supplier evidence", Target: "Supplier", Inputs: []product.ActionInput{{Name: "expected_revision", Type: "integer"}, {Name: "is_complete", Type: "boolean"}}, Programs: deferred("record_evidence"), Ceiling: product.ProgramCeiling{Reads: []product.ProgramRead{read("target", "key"), read("target", "evidence_revision"), read("input", "expected_revision"), read("input", "is_complete")}, Dependencies: []string{"Supplier"}, Effects: []product.ProgramEffectPermission{permission("set_properties", "Supplier", "evidence_revision", "evidence_complete")}, MaxEffects: 1, MaxValueBytes: 8192}, AllowedFor: yes, AllowedIf: policy(algebra.Compare(algebra.CompareEq, algebra.FieldRef("target", "evidence_revision"), algebra.FieldRef("input", "expected_revision"))), RequiresReview: no}),
		product.NewAction(product.Action{Name: "RequestOnboarding", Label: "Request onboarding", Creates: "OnboardingCase", KeyFrom: "case_id", Inputs: []product.ActionInput{{Name: "case_id", Type: "string"}, {Name: "supplier", Type: "object_ref", ObjectType: "Supplier"}}, Programs: deferred("request_onboarding"), Ceiling: product.ProgramCeiling{Reads: []product.ProgramRead{read("input", "case_id"), read("input", "supplier", "supplier_id"), read("input", "supplier", "evidence_revision"), read("input", "supplier", "evidence_complete")}, Dependencies: []string{"Supplier", "OnboardingCase"}, Effects: []product.ProgramEffectPermission{permission("create_object", "OnboardingCase", "supplier_id", "status", "evidence_revision", "approved_revision", "findings"), permission("emit", "OnboardingRequested"), permission("start_workflow", "OnboardSupplier", "input")}, MaxEffects: 3, MaxValueBytes: 16384}, AllowedFor: yes, AllowedIf: yes, RequiresReview: no}),
		product.NewAction(product.Action{Name: "RecordOnboardingFindings", Target: "OnboardingCase", Inputs: []product.ActionInput{{Name: "supplier_id", Type: "string"}, {Name: "evidence_revision", Type: "integer"}, {Name: "status", Type: "string", Labels: []string{"needs_evidence", "awaiting_approval"}}, {Name: "findings", Type: "string"}}, Programs: deferred("record_findings"), Ceiling: product.ProgramCeiling{Reads: []product.ProgramRead{read("target", "key"), read("target", "supplier_id"), read("input", "supplier_id"), read("input", "evidence_revision"), read("input", "status"), read("input", "findings")}, Dependencies: []string{"OnboardingCase"}, Effects: []product.ProgramEffectPermission{permission("set_properties", "OnboardingCase", "evidence_revision", "status", "findings")}, MaxEffects: 1, MaxValueBytes: 8192}, AllowedFor: yes, AllowedIf: policy(algebra.Compare(algebra.CompareEq, algebra.FieldRef("target", "supplier_id"), algebra.FieldRef("input", "supplier_id"))), RequiresReview: no}),
		product.NewAction(product.Action{Name: "ApproveSupplier", Label: "Approve supplier", Target: "OnboardingCase", Inputs: []product.ActionInput{{Name: "supplier", Type: "object_ref", ObjectType: "Supplier"}, {Name: "evidence_revision", Type: "integer"}}, Programs: deferred("approve_supplier"), Ceiling: product.ProgramCeiling{Reads: []product.ProgramRead{read("target", "key"), read("target", "supplier_id"), read("target", "status"), read("target", "evidence_revision"), read("input", "supplier", "supplier_id"), read("input", "supplier", "evidence_revision"), read("input", "supplier", "evidence_complete"), read("input", "evidence_revision")}, Dependencies: []string{"Supplier", "OnboardingCase"}, Effects: []product.ProgramEffectPermission{permission("set_properties", "OnboardingCase", "approved_revision", "status")}, MaxEffects: 1, MaxValueBytes: 8192}, AllowedFor: yes, AllowedIf: policy(algebra.And(algebra.Compare(algebra.CompareEq, algebra.FieldRef("target", "supplier_id"), algebra.FieldPath("input", "supplier", "supplier_id")), algebra.Compare(algebra.CompareEq, algebra.FieldRef("target", "status"), algebra.Literal(text("awaiting_approval"))), algebra.Compare(algebra.CompareEq, algebra.FieldRef("target", "evidence_revision"), algebra.FieldRef("input", "evidence_revision")), algebra.Compare(algebra.CompareEq, algebra.FieldPath("input", "supplier", "evidence_revision"), algebra.FieldRef("input", "evidence_revision")), algebra.Compare(algebra.CompareEq, algebra.FieldPath("input", "supplier", "evidence_complete"), algebra.Literal(av.Bool(true))))), RequiresReview: yes}),
		product.NewAction(product.Action{Name: "ActivateSupplier", Target: "OnboardingCase", Inputs: []product.ActionInput{{Name: "supplier", Type: "object_ref", ObjectType: "Supplier"}, {Name: "evidence_revision", Type: "integer"}}, Programs: deferred("activate_supplier"), Ceiling: product.ProgramCeiling{Reads: []product.ProgramRead{read("target", "key"), read("target", "supplier_id"), read("target", "status"), read("target", "approved_revision"), read("input", "supplier", "supplier_id"), read("input", "supplier", "evidence_revision"), read("input", "evidence_revision")}, Dependencies: []string{"Supplier", "OnboardingCase"}, Effects: []product.ProgramEffectPermission{permission("set_properties", "Supplier", "is_active"), permission("set_properties", "OnboardingCase", "status")}, MaxEffects: 2, MaxValueBytes: 8192}, AllowedFor: yes, AllowedIf: policy(algebra.And(algebra.Compare(algebra.CompareEq, algebra.FieldRef("target", "supplier_id"), algebra.FieldPath("input", "supplier", "supplier_id")), algebra.Compare(algebra.CompareEq, algebra.FieldRef("target", "status"), algebra.Literal(text("approved"))), algebra.Compare(algebra.CompareEq, algebra.FieldRef("target", "approved_revision"), algebra.FieldRef("input", "evidence_revision")), algebra.Compare(algebra.CompareEq, algebra.FieldPath("input", "supplier", "evidence_revision"), algebra.FieldRef("input", "evidence_revision")))), RequiresReview: no}),
	}
	return product.Product(product.Document{Algebra: algebraValue, Workflow: workflowValue, Actions: append(append(append(actions, supplierRiskActions()...), importerAction()), signatureActions()...), Connections: []product.Connection{importerConnection(), signatureConnection()}, Signals: []product.Signal{product.NewSignal(signatureChanged, "SignatureRequest", product.Publishers([]string{"human", "service"}, product.CausationActionRequired))},
		Automations: []product.Automation{product.NewAutomation(product.Automation{Name: "investigate_supplier_risk",
			Description: "Independently investigate a supplier when its recorded risk becomes high.",
			Target:      product.WorkflowTarget("InvestigateSupplier"),
			Trigger:     product.OnObjectPropertiesSet("Supplier", []string{"is_high_risk"}, map[string]product.ValuePredicate{"is_high_risk": product.Predicate("eq", module.Bool(true))}),
			Arguments:   map[string]product.Argument{"supplier_id": product.Occurrence(product.OccurrenceSubjectKey)}})},
		Events:        []product.Event{product.NewEvent("OnboardingRequested", "OnboardingCase", product.EventProperty{Name: "case_id", Type: "string"}, product.EventProperty{Name: "supplier_id", Type: "string"}, product.EventProperty{Name: "evidence_revision", Type: "integer"}, product.EventProperty{Name: "evidence_complete", Type: "boolean"})},
		PublicObjects: []product.PublicObjectsSpec{{Every: true}}, Dashboards: []product.Dashboard{{Name: "supplier_onboarding", Title: "Supplier onboarding", Filters: []product.DashboardFilter{}, Panels: []product.FunctionPanel{{ID: "cases", Title: "Cases", Layout: product.GridLayout{X: 0, Y: 0, W: 12, H: 6}, Source: product.FunctionPanelSource{Function: "onboarding_cases"}, View: product.Table([]string{"case_id", "supplier_id", "status", "evidence_revision", "findings"})}, {ID: "signature_requests", Title: "Signature requests", Layout: product.GridLayout{X: 0, Y: 6, W: 12, H: 6}, Source: product.FunctionPanelSource{Function: "signature_requests"}, View: product.Table([]string{"request_id", "case_id", "supplier_id", "document_revision", "requested_at", "reminder_at", "expires_at", "status", "delivery_id"})}}}}}), nil
}

func workflowDefinition() workflow.Definition {
	inputs := []workflow.Input{must(workflow.NewInput("case_id", av.TypeString, false, ""))}
	active := must(workflow.Reference("input.case_id"))
	code := must(workflow.NewCode(workflow.CodeOptions{Results: []workflow.Result{must(workflow.NewResult("needs_evidence", "Supplier evidence needed", workflow.DispositionAttention, inputs)), must(workflow.NewResult("complete", "Supplier activated", workflow.DispositionResolved, inputs))}, Module: "onboarding_workflow", Entrypoint: "run", Functions: []string{"assess_supplier"}, Actions: []string{"RecordOnboardingFindings", "ApproveSupplier", "ActivateSupplier"}, MaxOperations: 8, MaxHistoryBytes: 65536, MaxReplayFuel: 10000000}))
	spec := must(workflow.NewSpec("OnboardSupplier", workflow.SpecOptions{Label: "Onboard supplier", Description: "Assess evidence, retain findings, obtain ordinary Action review, and activate against the same revision.", Inputs: inputs, ActiveKey: &active, Code: &code, MaxDuration: "168h", MaxFunctionRuns: 8}))
	return must(workflow.NewDefinition([]workflow.Spec{spec, supplierRiskWorkflow(), adaptiveImporterWorkflow(), collectSignatureWorkflow()}))
}

type facts struct {
	Target map[string]av.Value `json:"target"`
	Input  map[string]av.Value `json:"input"`
}

func decodeFacts(value module.Value) (facts, error) {
	var out facts
	raw, err := value.MarshalJSON()
	if err == nil {
		err = json.Unmarshal(raw, &out)
	}
	return out, err
}
func expression(root, name string) aa.ValueExpr {
	return must(aa.Reference(must(aa.NewReadRef(aa.ReadRoot(root), name))))
}
func literal(value av.Value) aa.ValueExpr { return must(aa.Literal(value)) }
func field(name string, value aa.ValueExpr) aa.NamedValueExpr {
	return must(aa.NewNamedValueExpr(name, value))
}
func output(effects []aa.Effect, reads []aa.ReadRef, dependencies []string, permissions []aa.EffectPermission) (module.Value, error) {
	ceiling := must(aa.NewCeiling(aa.CeilingOptions{Reads: reads, Dependencies: dependencies, Effects: permissions, MaxEffects: len(effects), MaxValueBytes: 16384}))
	raw, err := json.Marshal(must(aa.NewEffectsOutput(effects, ceiling)))
	if err != nil {
		return module.Value{}, err
	}
	return module.ParseDocumentJSON(raw)
}
func refs(items ...[2]string) []aa.ReadRef {
	out := make([]aa.ReadRef, len(items))
	for i, item := range items {
		out[i] = must(aa.NewReadRef(aa.ReadRoot(item[0]), item[1]))
	}
	return out
}
func perm(kind aa.EffectKind, name string, fields ...string) aa.EffectPermission {
	return must(aa.NewEffectPermission(kind, name, fields...))
}
func set(object, line string, target aa.ValueExpr, fields ...aa.NamedValueExpr) aa.Effect {
	return must(aa.NewEffect(aa.EffectSetProperties, object, line, &target, fields))
}
func create(object, line string, target aa.ValueExpr, fields ...aa.NamedValueExpr) aa.Effect {
	return must(aa.NewEffect(aa.EffectCreateObject, object, line, &target, fields))
}

func registerSupplier(_ module.Context, _ module.Value) (module.Value, error) {
	e := create("Supplier", "Register supplier", expression("input", "supplier_id"), field("name", expression("input", "name")), field("is_active", literal(av.Bool(false))), field("evidence_revision", literal(av.Int64(0))), field("evidence_complete", literal(av.Bool(false))), field("is_high_risk", literal(av.Bool(false))), field("risk_revision", literal(av.Int64(0))))
	return output([]aa.Effect{e}, refs([2]string{"input", "supplier_id"}, [2]string{"input", "name"}), []string{"Supplier"}, []aa.EffectPermission{perm(aa.EffectCreateObject, "Supplier", "name", "is_active", "evidence_revision", "evidence_complete", "is_high_risk", "risk_revision")})
}
func recordEvidence(_ module.Context, v module.Value) (module.Value, error) {
	f, err := decodeFacts(v)
	if err != nil {
		return module.Value{}, err
	}
	current, _ := f.Target["evidence_revision"].Int64()
	e := set("Supplier", "Record supplier evidence", expression("target", "key"), field("evidence_revision", literal(av.Int64(current+1))), field("evidence_complete", expression("input", "is_complete")))
	return output([]aa.Effect{e}, refs([2]string{"target", "key"}, [2]string{"target", "evidence_revision"}, [2]string{"input", "expected_revision"}, [2]string{"input", "is_complete"}), []string{"Supplier"}, []aa.EffectPermission{perm(aa.EffectSetProperties, "Supplier", "evidence_revision", "evidence_complete")})
}
func requestOnboarding(_ module.Context, _ module.Value) (module.Value, error) {
	target := expression("input", "case_id")
	createCase := create("OnboardingCase", "Create onboarding case", target, field("supplier_id", must(aa.Reference(must(aa.NewReadRef(aa.ReadInput, "supplier", "supplier_id"))))), field("status", literal(text("requested"))), field("evidence_revision", must(aa.Reference(must(aa.NewReadRef(aa.ReadInput, "supplier", "evidence_revision"))))), field("approved_revision", literal(av.Null())), field("findings", literal(text("Assessment pending."))))
	requested := must(aa.NewEffect(aa.EffectEmit, "OnboardingRequested", "Request supplier onboarding", &target, []aa.NamedValueExpr{field("case_id", expression("input", "case_id")), field("supplier_id", must(aa.Reference(must(aa.NewReadRef(aa.ReadInput, "supplier", "supplier_id"))))), field("evidence_revision", must(aa.Reference(must(aa.NewReadRef(aa.ReadInput, "supplier", "evidence_revision"))))), field("evidence_complete", must(aa.Reference(must(aa.NewReadRef(aa.ReadInput, "supplier", "evidence_complete")))))}))
	reads := []aa.ReadRef{must(aa.NewReadRef(aa.ReadInput, "case_id")), must(aa.NewReadRef(aa.ReadInput, "supplier", "supplier_id")), must(aa.NewReadRef(aa.ReadInput, "supplier", "evidence_revision")), must(aa.NewReadRef(aa.ReadInput, "supplier", "evidence_complete"))}
	started := must(aa.NewStartWorkflowEffect("OnboardSupplier", "Admit supplier onboarding", must(aa.Object(field("case_id", expression("input", "case_id"))))))
	return output([]aa.Effect{createCase, requested, started}, reads, []string{"Supplier", "OnboardingCase"}, []aa.EffectPermission{perm(aa.EffectCreateObject, "OnboardingCase", "supplier_id", "status", "evidence_revision", "approved_revision", "findings"), perm(aa.EffectEmit, "OnboardingRequested"), perm(aa.EffectStartWorkflow, "OnboardSupplier", "input")})
}
func recordFindings(_ module.Context, _ module.Value) (module.Value, error) {
	e := set("OnboardingCase", "Record assessment findings", expression("target", "key"), field("evidence_revision", expression("input", "evidence_revision")), field("status", expression("input", "status")), field("findings", expression("input", "findings")))
	return output([]aa.Effect{e}, refs([2]string{"target", "key"}, [2]string{"target", "supplier_id"}, [2]string{"input", "supplier_id"}, [2]string{"input", "evidence_revision"}, [2]string{"input", "status"}, [2]string{"input", "findings"}), []string{"OnboardingCase"}, []aa.EffectPermission{perm(aa.EffectSetProperties, "OnboardingCase", "evidence_revision", "status", "findings")})
}
func approveSupplier(_ module.Context, _ module.Value) (module.Value, error) {
	e := set("OnboardingCase", "Approve exact supplier evidence", expression("target", "key"), field("approved_revision", expression("input", "evidence_revision")), field("status", literal(text("approved"))))
	reads := []aa.ReadRef{must(aa.NewReadRef(aa.ReadTarget, "key")), must(aa.NewReadRef(aa.ReadTarget, "supplier_id")), must(aa.NewReadRef(aa.ReadTarget, "status")), must(aa.NewReadRef(aa.ReadTarget, "evidence_revision")), must(aa.NewReadRef(aa.ReadInput, "supplier", "supplier_id")), must(aa.NewReadRef(aa.ReadInput, "supplier", "evidence_revision")), must(aa.NewReadRef(aa.ReadInput, "supplier", "evidence_complete")), must(aa.NewReadRef(aa.ReadInput, "evidence_revision"))}
	return output([]aa.Effect{e}, reads, []string{"Supplier", "OnboardingCase"}, []aa.EffectPermission{perm(aa.EffectSetProperties, "OnboardingCase", "approved_revision", "status")})
}
func activateSupplier(_ module.Context, _ module.Value) (module.Value, error) {
	supplier := must(aa.Reference(must(aa.NewReadRef(aa.ReadInput, "supplier"))))
	first := set("Supplier", "Activate supplier", supplier, field("is_active", literal(av.Bool(true))))
	second := set("OnboardingCase", "Complete onboarding case", expression("target", "key"), field("status", literal(text("complete"))))
	reads := []aa.ReadRef{must(aa.NewReadRef(aa.ReadTarget, "key")), must(aa.NewReadRef(aa.ReadTarget, "supplier_id")), must(aa.NewReadRef(aa.ReadTarget, "status")), must(aa.NewReadRef(aa.ReadTarget, "approved_revision")), must(aa.NewReadRef(aa.ReadInput, "supplier")), must(aa.NewReadRef(aa.ReadInput, "supplier", "supplier_id")), must(aa.NewReadRef(aa.ReadInput, "supplier", "evidence_revision")), must(aa.NewReadRef(aa.ReadInput, "evidence_revision"))}
	return output([]aa.Effect{first, second}, reads, []string{"Supplier", "OnboardingCase"}, []aa.EffectPermission{perm(aa.EffectSetProperties, "Supplier", "is_active"), perm(aa.EffectSetProperties, "OnboardingCase", "status")})
}
