package types

import (
	"encoding/json"
	"fmt"
)

// Nullable[T] - Generischer Typ für optionale Werte (nullable fields)
type Nullable[T any] struct {
	Value *T   // Der tatsächliche Wert (kann nil sein)
	Valid bool // Gibt an, ob der Wert gesetzt wurde
}

// NewNullable erstellt eine gültige Nullable-Instanz
func NewNullable[T any](value T) Nullable[T] {
	return Nullable[T]{Value: &value, Valid: true}
}

// Null erstellt eine leere Nullable-Instanz (ungesetzt)
func Null[T any]() Nullable[T] {
	return Nullable[T]{Valid: true}
}

func Undefined[T any]() Nullable[T] {
	return Nullable[T]{Valid: false}
}

// MarshalJSON - Serialisiert `Nullable[T]` korrekt ins JSON-Format
func (n Nullable[T]) MarshalJSON() ([]byte, error) {
	if !n.Valid {
		return []byte("null"), nil // Wenn nicht valid, dann NULL
	}
	return json.Marshal(n.Value) // Serialisiert den tatsächlichen Wert
}

// UnmarshalJSON - Deserialisiert JSON in `Nullable[T]`
func (n *Nullable[T]) UnmarshalJSON(data []byte) error {
	if string(data) == "null" {
		n.Valid = true // Wert wurde gesetzt, aber auf NULL
		n.Value = nil  // Explizit NULL setzen
		return nil
	}

	var v T
	if err := json.Unmarshal(data, &v); err != nil {
		return fmt.Errorf("invalid JSON for Nullable: %w", err)
	}

	n.Value = &v
	n.Valid = true
	return nil
}
