package services

import (
	"context"
	"sync"
	"time"

	"github.com/fiskerinc/cloud-services/pkg/mongo"
	"github.com/pkg/errors"
	"github.com/sony/gobreaker"
)

var (
	clientlock sync.Mutex
	client     mongo.Client
	cb         *gobreaker.CircuitBreaker
)

func init() {
	cb = gobreaker.NewCircuitBreaker(
		gobreaker.Settings{
			Timeout:  10 * time.Second,
			Interval: 15 * time.Minute,
		},
	)
}

// GetMongoClient returns singleton instance of mongo client
func GetMongoClient() (mongo.Client, error) {
	err := ping()
	if err != nil {
		return initMongoClient()
	}

	return client, nil
}

func initMongoClient() (mongo.Client, error) {
	clientlock.Lock()
	defer clientlock.Unlock()
	var err error

	client, err = mongo.NewClient(mongo.StandardDB)
	if err != nil {
		return nil, err
	}

	_, _ = cb.Execute(func() (interface{}, error) {
		err = ping()
		return nil, err
	})

	return client, errors.WithStack(err)
}

func ping() error {
	if client == nil {
		return errors.New("client is nil")
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
	defer cancel()
	return client.Ping(ctx)
}

// SetMongoClient is supposed to be used for tests.
func SetMongoClient(cl mongo.Client) {
	client = cl
}


// db.dtc_lookup.aggregate({"$match": {"ecuName": "TBOX", "DtcUniqueId": "V2.6.0"}}, {"$unwind": "$dtcData.DtcList"}, {"$match": {"dtcData.DtcList.TroubleCodeHex":"D77F16"}}, {"$project":{"_id": 0, "Obj": "$dtcData.DtcList"}})