package decoders

import (
	"fmt"

	"git.max-richter.dev/max/marka/parser/utils"
	renderUtils "git.max-richter.dev/max/marka/renderer/utils"
	"git.max-richter.dev/max/marka/template"
	"go.yaml.in/yaml/v4"
)

func Yaml(input string, block template.Block) (value any, error error) {
	res := make(map[string]any)
	err := yaml.Unmarshal([]byte(input), &res)
	if err != nil {
		return nil, fmt.Errorf("failed to parse yaml '%q': %w", input, err)
	}

	var out any // Keep out as any
	for _, f := range block.Fields {

		if f.Path == "@schema" {
			continue
		}

		if f.CodecType == template.CodecConst {
			if f.Value != nil {
				// Only set const value if 'out' is a map and the path doesn't exist
				if outMap, ok := out.(map[string]any); ok {
					if _, exists := renderUtils.GetValueFromPath(outMap, f.Path); !exists {
						out = utils.SetPathValue(f.Path, f.Value, out)
					}
				} else if out == nil { // If out is nil, it's the first value, so set it
					out = utils.SetPathValue(f.Path, f.Value, out)
				}
			}
		} else {
			if value, ok := res[f.Path]; ok {
				out = utils.SetPathValue(f.Path, value, out)
				continue
			}

			for _, alias := range f.PathAliases {
				if value, ok := res[alias]; ok {
					out = utils.SetPathValue(f.Path, value, out)
					continue
				}
			}

			if value, ok := renderUtils.GetValueFromPath(res, f.Path); ok {
				out = utils.SetPathValue(f.Path, value, out)
				continue
			}
		}
	}

	return out, nil
}
