# evalv3 regression: nested if-comprehensions inside a definition accessed via
# a for-comprehension over a pattern-constrained struct incorrectly produced an
# "incomplete value" error. The if-comprehensions (e.g. strings.HasSuffix
# guards) failed to evaluate when the definition was reached through multiple
# layers of embedding (_#cronjob → _#pod → _#container). evalv2 (v0.12.1)
# accepted the code correctly.
# https://cuelang.org/issue/3929
-- in.cue --
package main

import "strings"

reduced: {
	#Input: {
		@test(shareID=reducedInput)
		name:  string
		age:   "one" | "two"
		if name != _|_ {
			if true {
				age: "one"
			}
		}
	}

	#def1: {
		IN=_in: _
		def1: #def2 & {_in: IN}
	}

	#def2: {
		IN=_in: _
		def2: #def3 & {_in: IN}
	}

	#def3: {
		_in: #Input @test(shareID=reducedInput)
		def3: _in.age
	}

	in: name: "foobar"

	out: (#def1 & {_in: in}).def1
	@test(eq, {
		#Input: {name: string, age: "one" | "two"}
		#def1: {
			_in$main: _
			def1: {
				_in$main: _
				def2: {
					_in$main: {name: string, age: "one" | "two"}
					def3: "one" | "two"
				}
			}
		}
		#def2: {
			_in$main: _
			def2: {
				_in$main: {name: string, age: "one" | "two"}
				def3: "one" | "two"
			}
		}
		#def3: {
			_in$main: {name: string, age: "one" | "two"}
			def3: "one" | "two"
		}
		in: {name: "foobar"}
		out: {
			_in$main: {name: "foobar"}
			def2: {
				_in$main: {name: "foobar", age: "one"}
				def3: "one"
			}
		}
	})
}

full: {
	cronjob: [string]: #CronjobConfig

	#CronjobConfig: {
		@test(shareID=cronjobConfig)
		#PodConfig
	}

	#PodConfig: {
		@test(shareID=podConfig)
		#ContainerConfig
	}

	#ContainerConfig: {
		@test(shareID=containerConfig)
		image:           string
		imagePullPolicy: "IfNotPresent" | "Always" | "Never"
		if image != _|_ {
			if strings.HasSuffix(image, ":latest") == true {
				imagePullPolicy: "IfNotPresent" | *"Always" | "Never"
			}
			if strings.HasSuffix(image, ":latest") != true {
				imagePullPolicy: *"IfNotPresent" | "Always" | "Never"
			}
		}
	}

	_#cronjob: {
		c=_config: #CronjobConfig @test(shareID=cronjobConfig)

		out: spec: jobTemplate: spec: template: _#pod & {_config: c}
	}

	_#pod: {
		c=_config: #PodConfig @test(shareID=podConfig)

		spec: containers: [{
			_#container & {
				_config: c
			}
		}]
	}

	_#container: {
		c=_config: #ContainerConfig @test(shareID=containerConfig)

		imagePullPolicy: c.imagePullPolicy
	}

	cronjob: "foobar": image: "foobar:latest"

	for k, v in cronjob {
		objects: cronjob: "\(k)": (_#cronjob & {_config: v}).out
	}
	@test(eq, hint="update this once todo is fixed", {
		cronjob: foobar: {
			image:           "foobar:latest"
			imagePullPolicy: *"Always" | "IfNotPresent" | "Never"
		}
		#CronjobConfig: {
			image:           string
			imagePullPolicy: "IfNotPresent" | "Always" | "Never"
		}
		#PodConfig: {
			image:           string
			imagePullPolicy: "IfNotPresent" | "Always" | "Never"
		}
		#ContainerConfig: {
			image:           string
			imagePullPolicy: "IfNotPresent" | "Always" | "Never"
		}
		_#cronjob$main: {
			_config$main: {
				image:           string
				imagePullPolicy: "IfNotPresent" | "Always" | "Never"
			}
			out: spec: jobTemplate: spec: template: {
				_config$main: {
					image:           string
					imagePullPolicy: "IfNotPresent" | "Always" | "Never"
				}
				spec: containers: [{
					_config$main:    _ @test(ignore)
					imagePullPolicy: "IfNotPresent" | "Always" | "Never"
				}]
			}
		}
		_#pod$main: {
			_config$main: {
				image:           string
				imagePullPolicy: "IfNotPresent" | "Always" | "Never"
			}
			spec: containers: [{
				_config$main:    _ @test(ignore)
				imagePullPolicy: "IfNotPresent" | "Always" | "Never"
			}]
		}
		_#container$main: {
			_config$main: {
				image:           string
				imagePullPolicy: "IfNotPresent" | "Always" | "Never"
			}
			imagePullPolicy: "IfNotPresent" | "Always" | "Never"
		}
		objects: cronjob: foobar: spec: jobTemplate: spec: template: {
			_config$main: {
				image:           "foobar:latest"
				imagePullPolicy: *"Always" | "IfNotPresent" | "Never"
			}
			spec: containers: [{
				_config$main:    _ @test(ignore)
				imagePullPolicy: *"Always" | "IfNotPresent" | "Never"
			}]
		}
	})
	// TODO(inline) support at for closed.
	// @test(closed, at=full.objects.cronjob.foobar)

}
-- out/todo.txt --
reduced.#def3._in: v3 shows ~(reduced.#Input) (structure sharing) where v2
expands the full struct.
full._#cronjob, full._#pod, full._#container: v3 uses structure sharing for
_config fields where v2 expands them.
reduced.out.def2._in.age, reduced.out.def2.def3: pushdown resolves the
comprehension condition "if name != _|_" when name is concrete ("foobar"),
correctly collapsing age from "one" | "two" to "one". Previously this was
left unresolved.
full.objects.cronjob.foobar...imagePullPolicy: pushdown resolves the
comprehension condition "if image != _|_" when image is "foobar:latest",
correctly applying the default *"Always". Previously left without a default.
full.cronjob.foobar.imagePullPolicy: same as above — default now propagates
to the cronjob field itself.
-- out/eval/stats --
Leaks:  1
Freed:  161
Reused: 127
Allocs: 35
Retain: 0

Unifications: 96
Conjuncts:    275
Disjuncts:    62

NumCloseIDs: 102

ConjunctInfos:       166
MaxConjunctInfos:    8
MaxReqSets:          15
MaxRedirect:         3
