package exerr

import (
	"context"
	"encoding/json"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"gogs.mikescher.com/BlackForestBytes/goext/tst"
	"testing"
	"time"
)

func TestJSONMarshalErrorCategory(t *testing.T) {

	c1 := CatSystem

	jsonbin := tst.Must(json.Marshal(c1))(t)

	var c2 ErrorCategory
	tst.AssertNoErr(t, json.Unmarshal(jsonbin, &c2))

	tst.AssertEqual(t, c1, c2)

	tst.AssertEqual(t, string(jsonbin), "\"System\"")
}

func TestJSONMarshalErrorSeverity(t *testing.T) {

	c1 := SevErr

	jsonbin := tst.Must(json.Marshal(c1))(t)

	var c2 ErrorSeverity
	tst.AssertNoErr(t, json.Unmarshal(jsonbin, &c2))

	tst.AssertEqual(t, c1, c2)

	tst.AssertEqual(t, string(jsonbin), "\"Err\"")
}

func TestJSONMarshalErrorType(t *testing.T) {

	c1 := TypeNotImplemented

	jsonbin := tst.Must(json.Marshal(c1))(t)

	var c2 ErrorType
	tst.AssertNoErr(t, json.Unmarshal(jsonbin, &c2))

	tst.AssertEqual(t, c1, c2)

	tst.AssertEqual(t, string(jsonbin), "\"NOT_IMPLEMENTED\"")
}

func TestBSONMarshalErrorCategory(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), 350*time.Millisecond)
	defer cancel()

	client, err := mongo.Connect(ctx)
	if err != nil {
		t.Skip("Skip test - no local mongo found")
		return
	}
	err = client.Ping(ctx, nil)
	if err != nil {
		t.Skip("Skip test - no local mongo found")
		return
	}

	primimd := primitive.NewObjectID()

	_, err = client.Database("_test").Collection("goext-cicd").InsertOne(ctx, bson.M{"_id": primimd, "val": CatSystem})
	tst.AssertNoErr(t, err)

	cursor := client.Database("_test").Collection("goext-cicd").FindOne(ctx, bson.M{"_id": primimd, "val": bson.M{"$type": "string"}})

	var c1 struct {
		ID  primitive.ObjectID `bson:"_id"`
		Val ErrorCategory      `bson:"val"`
	}

	err = cursor.Decode(&c1)
	tst.AssertNoErr(t, err)

	tst.AssertEqual(t, c1.Val, CatSystem)
}

func TestBSONMarshalErrorSeverity(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), 350*time.Millisecond)
	defer cancel()

	client, err := mongo.Connect(ctx)
	if err != nil {
		t.Skip("Skip test - no local mongo found")
		return
	}
	err = client.Ping(ctx, nil)
	if err != nil {
		t.Skip("Skip test - no local mongo found")
		return
	}

	primimd := primitive.NewObjectID()

	_, err = client.Database("_test").Collection("goext-cicd").InsertOne(ctx, bson.M{"_id": primimd, "val": SevErr})
	tst.AssertNoErr(t, err)

	cursor := client.Database("_test").Collection("goext-cicd").FindOne(ctx, bson.M{"_id": primimd, "val": bson.M{"$type": "string"}})

	var c1 struct {
		ID  primitive.ObjectID `bson:"_id"`
		Val ErrorSeverity      `bson:"val"`
	}

	err = cursor.Decode(&c1)
	tst.AssertNoErr(t, err)

	tst.AssertEqual(t, c1.Val, SevErr)
}

func TestBSONMarshalErrorType(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), 350*time.Millisecond)
	defer cancel()

	client, err := mongo.Connect(ctx)
	if err != nil {
		t.Skip("Skip test - no local mongo found")
		return
	}
	err = client.Ping(ctx, nil)
	if err != nil {
		t.Skip("Skip test - no local mongo found")
		return
	}

	primimd := primitive.NewObjectID()

	_, err = client.Database("_test").Collection("goext-cicd").InsertOne(ctx, bson.M{"_id": primimd, "val": TypeNotImplemented})
	tst.AssertNoErr(t, err)

	cursor := client.Database("_test").Collection("goext-cicd").FindOne(ctx, bson.M{"_id": primimd, "val": bson.M{"$type": "string"}})

	var c1 struct {
		ID  primitive.ObjectID `bson:"_id"`
		Val ErrorType          `bson:"val"`
	}

	err = cursor.Decode(&c1)
	tst.AssertNoErr(t, err)

	tst.AssertEqual(t, c1.Val, TypeNotImplemented)
}