package operator

import (
	"encoding/json"
	"fmt"
	"testing"

	"go.mongodb.org/mongo-driver/bson"
)

func TestModify(t *testing.T) {
	cases := map[string]struct {
		marshalme interface{}
		key1      string
		key2      string
		want      interface{}
	}{
		"unset": {
			marshalme: Unset("field"),
			key1:      "field",
			key2:      "$unset",
			want:      nil,
		},
		"popif": {
			marshalme: PopIf{Key: "field", Filter: "world"},
			key1:      "$pull",
			key2:      "field",
			want:      "world",
		},
		"popif map": {
			marshalme: PopIf{Key: "field", Filter: map[string]string{"world": "jk"}},
			key1:      "$pull",
			key2:      "field",
			want:      map[string]string{"world": "jk"},
		},
		"set": {
			marshalme: Set{Key: "field", Value: "value"},
			key1:      "$set",
			key2:      "field",
			want:      "value",
		},
		"push": {
			marshalme: Push{Key: "field", Value: "value"},
			key1:      "$push",
			key2:      "field",
			want:      "value",
		},
	}

	for name, d := range cases {
		c := d
		t.Run(name, func(t *testing.T) {
			var v map[string]map[string]interface{}
			if b, err := bson.Marshal(c.marshalme); err != nil {
				t.Error(err)
			} else if err := bson.Unmarshal(b, &v); err != nil {
				t.Error(err)
			} else if got := v[c.key1][c.key2]; fmt.Sprint(got) != fmt.Sprint(c.want) {
				a, _ := json.Marshal(got)
				b, _ := json.Marshal(v)
				t.Errorf("want [%s][%s] = %v, got %s from %s", c.key1, c.key2, c.want, string(a), string(b))
			}
		})
	}
}
