package fix

import (
	"log/slog"
	"time"

	"quantex.com/qfixdpl/src/common/tracerr"
)

// FixField identifies a single FIX field by its dictionary metadata.
type FixField struct {
	Name string
	Tag  int
	Type string
}

// FieldValue is the typed value for a FIX field.
type FieldValue interface{}

// FieldMap is the enriched representation of a FIX FieldMap (header, body, or trailer).
type FieldMap map[FixField]FieldValue

// GetMap converts a FieldMap into a JSON-friendly map keyed by field name.
func GetMap(fieldMap FieldMap) map[string]interface{} {
	result := map[string]interface{}{}

	for f, v := range fieldMap {
		slog.Info("try to parse fieldMap: %+v, value: %+v", f, v)
		k, val := GetKeyValue(f, v)
		result[k] = val
	}

	return result
}

//nolint:funlen,gocyclo,cyclop //it's long but easy to read
func GetKeyValue(f FixField, value FieldValue) (key string, val interface{}) {
	key = f.Name

	switch f.Type {
	case "NUMINGROUP":
		var groups []map[string]interface{}

		fMapLst, ok := value.([]FieldMap)
		if !ok {
			err := tracerr.Errorf("could not parse as []FieldMap, value: %+v, key: %s", value, key)
			slog.Error(err.Error())
		}

		for _, fieldMap := range fMapLst {
			groups = append(groups, GetMap(fieldMap))
		}

		val = groups
	case "BOOLEAN":
		b, ok := value.(bool)
		if !ok {
			err := tracerr.Errorf("could not parse as bool, value: %+v, key: %s", value, key)
			slog.Error(err.Error())
		}

		val = b
	case "INT", "LENGTH", "SEQNUM":
		i, ok := value.(int)
		if !ok {
			err := tracerr.Errorf("could not parse as int, value: %+v, key: %s", value, key)
			slog.Error(err.Error())
		}

		val = i
	case "UTCTIMESTAMP":
		t, ok := value.(time.Time)
		if !ok {
			err := tracerr.Errorf("could not parse as Time, value: %+v, key: %s", value, key)
			slog.Error(err.Error())
		}

		val = t
	case "STRING":
		s, ok := value.(string)
		if !ok {
			err := tracerr.Errorf("could not parse as string, value: %+v, key: %s", value, key)
			slog.Error(err.Error())
		}

		val = s
	case "CHAR":
		s, ok := value.(string)
		if !ok {
			err := tracerr.Errorf("could not parse as string, value: %+v, key: %s", value, key)
			slog.Error(err.Error())
		}

		val = s
	default:
		s, ok := value.(string)
		if !ok {
			err := tracerr.Errorf("could not parse as string, value: %+v, key: %s", value, key)
			slog.Error(err.Error())
		}

		val = s
	}

	return key, val
}
