/*
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
Copyright (C) ITsysCOM GmbH

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>
*/

package cdrs

import (
	"reflect"
	"testing"
	"time"

	"github.com/cgrates/birpc"
	"github.com/cgrates/birpc/context"
	"github.com/cgrates/cgrates/config"
	"github.com/cgrates/cgrates/engine"
	"github.com/cgrates/cgrates/utils"
)

func TestCDRsV1ProcessEventMock(t *testing.T) {
	testCache := engine.Cache
	tmpC := config.CgrConfig()
	defer func() {
		engine.Cache = testCache
		config.SetCgrConfig(tmpC)
	}()

	cfg := config.NewDefaultCGRConfig()
	cfg.CdrsCfg().EEsConns = []string{utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs)}

	data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DbCfg().Items)
	connMng := engine.NewConnManager(cfg)
	dbCM := engine.NewDBConnManager(map[string]engine.DataDB{utils.MetaDefault: data}, cfg.DbCfg())
	dm := engine.NewDataManager(dbCM, cfg, nil)
	fltrs := engine.NewFilterS(cfg, nil, dm)
	engine.Cache = engine.NewCacheS(cfg, dm, nil, nil)
	newCDRSrv := NewCDRServer(cfg, dm, fltrs, connMng)
	ccM := &ccMock{
		calls: map[string]func(ctx *context.Context, args any, reply any) error{
			utils.EeSv1ProcessEvent: func(ctx *context.Context, args, reply any) error {
				*reply.(*map[string]map[string]any) = map[string]map[string]any{}
				return utils.ErrNotFound
			},
		},
	}
	rpcInternal := make(chan birpc.ClientConnector, 1)
	rpcInternal <- ccM
	newCDRSrv.connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs), utils.ThresholdSv1, rpcInternal)

	cgrEv := &utils.CGREvent{
		Event: map[string]any{
			"Resources":      "ResourceProfile1",
			utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC),
			"UsageInterval":  "1s",
			"PddInterval":    "1s",
			utils.Weight:     "20.0",
			utils.Usage:      135 * time.Second,
			utils.Cost:       123.0,
		},
		APIOpts: map[string]any{
			utils.OptsCDRsExport: true,
			"*context":           utils.MetaCDRs,
		},
	}
	var rply string
	err := newCDRSrv.V1ProcessEvent(context.Background(), cgrEv, &rply)
	if err != nil {
		t.Errorf("\nExpected <%+v> \n, received <%+v>", nil, err)
	}
	expected := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			"Resources":      "ResourceProfile1",
			utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC),
			"UsageInterval":  "1s",
			"PddInterval":    "1s",
			utils.Weight:     "20.0",
			utils.Usage:      135 * time.Second,
			utils.Cost:       123.0,
		},
		APIOpts: map[string]any{
			utils.OptsCDRsExport: true,
			"*context":           utils.MetaCDRs,
		},
	}
	cgrEv.ID = "testID"
	delete(cgrEv.APIOpts, utils.MetaCDRID) // ignore autogenerated *cdr field when comparing
	if !reflect.DeepEqual(expected, cgrEv) {
		t.Errorf("\nExpected <%+v> \n,received <%+v>", utils.ToJSON(expected), utils.ToJSON(cgrEv))
	}
}

func TestCDRsV1ProcessEventMockErr(t *testing.T) {
	testCache := engine.Cache
	tmpC := config.CgrConfig()
	defer func() {
		engine.Cache = testCache
		config.SetCgrConfig(tmpC)
	}()

	cfg := config.NewDefaultCGRConfig()
	cfg.CdrsCfg().EEsConns = []string{utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs)}

	data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DbCfg().Items)
	connMng := engine.NewConnManager(cfg)
	dbCM := engine.NewDBConnManager(map[string]engine.DataDB{utils.MetaDefault: data}, cfg.DbCfg())
	dm := engine.NewDataManager(dbCM, cfg, nil)
	fltrs := engine.NewFilterS(cfg, nil, dm)
	engine.Cache = engine.NewCacheS(cfg, dm, nil, nil)
	newCDRSrv := NewCDRServer(cfg, dm, fltrs, connMng)
	ccM := &ccMock{
		calls: map[string]func(ctx *context.Context, args any, reply any) error{
			utils.EeSv1ProcessEvent: func(ctx *context.Context, args, reply any) error {
				*reply.(*map[string]map[string]any) = map[string]map[string]any{}
				return utils.ErrNotFound
			},
		},
	}
	rpcInternal := make(chan birpc.ClientConnector, 1)
	rpcInternal <- ccM
	newCDRSrv.connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs), utils.ThresholdSv1, rpcInternal)

	cgrEv := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			"Resources":      "ResourceProfile1",
			utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC),
			"UsageInterval":  "1s",
			"PddInterval":    "1s",
			utils.Weight:     "20.0",
			utils.Usage:      135 * time.Second,
			utils.Cost:       123.0,
		},
		APIOpts: map[string]any{
			utils.MetaStats:      true,
			utils.OptsCDRsExport: true,
			"*context":           utils.MetaCDRs,
		},
	}
	var rply string
	err := newCDRSrv.V1ProcessEvent(context.Background(), cgrEv, &rply)
	if err == nil || err.Error() != "PARTIALLY_EXECUTED" {
		t.Errorf("\nExpected <%+v> \n, received <%+v>", "PARTIALLY_EXECUTED", err)
	}
	expected := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			"Resources":      "ResourceProfile1",
			utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC),
			"UsageInterval":  "1s",
			"PddInterval":    "1s",
			utils.Weight:     "20.0",
			utils.Usage:      135 * time.Second,
			utils.Cost:       123.0,
		},
		APIOpts: map[string]any{
			utils.MetaStats:      true,
			utils.OptsCDRsExport: true,
			"*context":           utils.MetaCDRs,
		},
	}
	delete(cgrEv.APIOpts, utils.MetaCDRID) // ignore autogenerated *cdr field when comparing
	if !reflect.DeepEqual(expected, cgrEv) {
		t.Errorf("\nExpected <%+v> \n,received <%+v>", expected, cgrEv)
	}
}

func TestCDRsV1ProcessEventMockCache(t *testing.T) {
	testCache := engine.Cache
	tmpC := config.CgrConfig()
	defer func() {
		engine.Cache = testCache
		config.SetCgrConfig(tmpC)
	}()

	cfg := config.NewDefaultCGRConfig()
	cfg.CdrsCfg().EEsConns = []string{utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs)}

	data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DbCfg().Items)
	connMng := engine.NewConnManager(cfg)
	dbCM := engine.NewDBConnManager(map[string]engine.DataDB{utils.MetaDefault: data}, cfg.DbCfg())
	dm := engine.NewDataManager(dbCM, cfg, nil)
	fltrs := engine.NewFilterS(cfg, nil, dm)
	engine.Cache = engine.NewCacheS(cfg, dm, nil, nil)
	newCDRSrv := NewCDRServer(cfg, dm, fltrs, connMng)
	ccM := &ccMock{
		calls: map[string]func(ctx *context.Context, args any, reply any) error{
			utils.EeSv1ProcessEvent: func(ctx *context.Context, args, reply any) error {
				*reply.(*map[string]map[string]any) = map[string]map[string]any{}
				return utils.ErrNotFound
			},
		},
	}
	rpcInternal := make(chan birpc.ClientConnector, 1)
	rpcInternal <- ccM
	newCDRSrv.connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs), utils.ThresholdSv1, rpcInternal)

	cgrEv := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			"Resources":      "ResourceProfile1",
			utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC),
			"UsageInterval":  "1s",
			"PddInterval":    "1s",
			utils.Weight:     "20.0",
			utils.Usage:      135 * time.Second,
			utils.Cost:       123.0,
		},
		APIOpts: map[string]any{
			utils.OptsCDRsExport: true,
			"*context":           utils.MetaCDRs,
		},
	}
	defaultConf := config.CgrConfig().CacheCfg().Partitions[utils.CacheRPCResponses]
	config.CgrConfig().CacheCfg().Partitions[utils.CacheRPCResponses].Limit = 1
	defer func() {
		config.CgrConfig().CacheCfg().Partitions[utils.CacheRPCResponses] = defaultConf
	}()
	var rply string
	err := newCDRSrv.V1ProcessEvent(context.Background(), cgrEv, &rply)
	if err != nil {
		t.Errorf("\nExpected <%+v> \n, received <%+v>", nil, err)
	}
	expected := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			"Resources":      "ResourceProfile1",
			utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC),
			"UsageInterval":  "1s",
			"PddInterval":    "1s",
			utils.Weight:     "20.0",
			utils.Usage:      135 * time.Second,
			utils.Cost:       123.0,
		},
		APIOpts: map[string]any{
			utils.OptsCDRsExport: true,
			"*context":           utils.MetaCDRs,
		},
	}
	delete(cgrEv.APIOpts, utils.MetaCDRID) // ignore autogenerated *cdr field when comparing
	if !reflect.DeepEqual(expected, cgrEv) {
		t.Errorf("\nExpected <%+v> \n,received <%+v>", expected, cgrEv)
	}
}

func TestCDRsV1ProcessEventWithGetMockCache(t *testing.T) {
	testCache := engine.Cache
	tmpC := config.CgrConfig()
	defer func() {
		engine.Cache = testCache
		config.SetCgrConfig(tmpC)
	}()

	cfg := config.NewDefaultCGRConfig()
	cfg.CdrsCfg().EEsConns = []string{utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs)}

	data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DbCfg().Items)
	connMng := engine.NewConnManager(cfg)
	dbCM := engine.NewDBConnManager(map[string]engine.DataDB{utils.MetaDefault: data}, cfg.DbCfg())
	dm := engine.NewDataManager(dbCM, cfg, nil)
	fltrs := engine.NewFilterS(cfg, nil, dm)
	engine.Cache = engine.NewCacheS(cfg, dm, nil, nil)
	newCDRSrv := NewCDRServer(cfg, dm, fltrs, connMng)
	ccM := &ccMock{
		calls: map[string]func(ctx *context.Context, args any, reply any) error{
			utils.EeSv1ProcessEvent: func(ctx *context.Context, args, reply any) error {
				*reply.(*map[string]map[string]any) = map[string]map[string]any{}
				return utils.ErrNotFound
			},
		},
	}
	rpcInternal := make(chan birpc.ClientConnector, 1)
	rpcInternal <- ccM
	newCDRSrv.connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs), utils.ThresholdSv1, rpcInternal)

	cgrEv := &utils.CGREvent{
		Event: map[string]any{
			"Resources":      "ResourceProfile1",
			utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC),
			"UsageInterval":  "1s",
			"PddInterval":    "1s",
			utils.Weight:     "20.0",
			utils.Usage:      135 * time.Second,
			utils.Cost:       123.0,
		},
		APIOpts: map[string]any{
			utils.OptsCDRsExport: true,
			"*context":           utils.MetaCDRs,
		},
	}
	defaultConf := config.CgrConfig().CacheCfg().Partitions[utils.CacheRPCResponses]
	config.CgrConfig().CacheCfg().Partitions[utils.CacheRPCResponses].Limit = 1
	defer func() {
		config.CgrConfig().CacheCfg().Partitions[utils.CacheRPCResponses] = defaultConf
	}()
	var rply []*utils.EventsWithOpts
	err := newCDRSrv.V1ProcessEventWithGet(context.Background(), cgrEv, &rply)
	if err != nil {
		t.Errorf("\nExpected <%+v> \n, received <%+v>", nil, err)
	}
	expected := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			"Resources":      "ResourceProfile1",
			utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC),
			"UsageInterval":  "1s",
			"PddInterval":    "1s",
			utils.Weight:     "20.0",
			utils.Usage:      135 * time.Second,
			utils.Cost:       123.0,
		},
		APIOpts: map[string]any{
			utils.OptsCDRsExport: true,
			"*context":           utils.MetaCDRs,
		},
	}
	cgrEv.ID = "testID"
	delete(cgrEv.APIOpts, utils.MetaCDRID) // ignore autogenerated *cdr field when comparing
	if !reflect.DeepEqual(expected, cgrEv) {
		t.Errorf("\nExpected <%+v> \n,received <%+v>", expected, cgrEv)
	}
}

func TestCDRsV1ProcessEventWithGetMockCacheErr(t *testing.T) {
	testCache := engine.Cache
	tmpC := config.CgrConfig()
	defer func() {
		engine.Cache = testCache
		config.SetCgrConfig(tmpC)
	}()

	cfg := config.NewDefaultCGRConfig()
	cfg.CdrsCfg().EEsConns = []string{utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs)}

	data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DbCfg().Items)
	connMng := engine.NewConnManager(cfg)
	dbCM := engine.NewDBConnManager(map[string]engine.DataDB{utils.MetaDefault: data}, cfg.DbCfg())
	dm := engine.NewDataManager(dbCM, cfg, nil)
	fltrs := engine.NewFilterS(cfg, nil, dm)
	engine.Cache = engine.NewCacheS(cfg, dm, nil, nil)
	newCDRSrv := NewCDRServer(cfg, dm, fltrs, connMng)
	ccM := &ccMock{
		calls: map[string]func(ctx *context.Context, args any, reply any) error{
			utils.EeSv1ProcessEvent: func(ctx *context.Context, args, reply any) error {
				*reply.(*map[string]map[string]any) = map[string]map[string]any{}
				return utils.ErrNotFound
			},
		},
	}
	rpcInternal := make(chan birpc.ClientConnector, 1)
	rpcInternal <- ccM
	newCDRSrv.connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs), utils.ThresholdSv1, rpcInternal)

	cgrEv := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			"Resources":      "ResourceProfile1",
			utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC),
			"UsageInterval":  "1s",
			"PddInterval":    "1s",
			utils.Weight:     "20.0",
			utils.Usage:      135 * time.Second,
			utils.Cost:       123.0,
		},
		APIOpts: map[string]any{
			utils.OptsCDRsExport: true,
			utils.MetaAttributes: time.Second,
			"*context":           utils.MetaCDRs,
		},
	}
	defaultConf := config.CgrConfig().CacheCfg().Partitions[utils.CacheRPCResponses]
	config.CgrConfig().CacheCfg().Partitions[utils.CacheRPCResponses].Limit = 1
	defer func() {
		config.CgrConfig().CacheCfg().Partitions[utils.CacheRPCResponses] = defaultConf
	}()
	expectedErr := `retrieving *attributes option failed: cannot convert field: 1s to bool`
	var rply []*utils.EventsWithOpts
	err := newCDRSrv.V1ProcessEventWithGet(context.Background(), cgrEv, &rply)
	if err == nil || err.Error() != expectedErr {
		t.Errorf("expected <%v>, received <%v>", expectedErr, err)
	}

}

func TestCDRsV1ProcessEventCacheGet(t *testing.T) {
	testCache := engine.Cache
	tmpC := config.CgrConfig()
	defer func() {
		engine.Cache = testCache
		config.SetCgrConfig(tmpC)
	}()

	cfg := config.NewDefaultCGRConfig()
	cfg.CacheCfg().Partitions[utils.CacheRPCResponses].Limit = 1

	data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DbCfg().Items)
	dbCM := engine.NewDBConnManager(map[string]engine.DataDB{utils.MetaDefault: data}, cfg.DbCfg())
	dm := engine.NewDataManager(dbCM, cfg, nil)
	fltrs := engine.NewFilterS(cfg, nil, dm)
	engine.Cache = engine.NewCacheS(cfg, dm, nil, nil)
	newCDRSrv := NewCDRServer(cfg, dm, fltrs, nil)
	cgrEv := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			utils.Cost: 123,
		},
	}

	rply := "string"
	engine.Cache.Set(context.Background(), utils.CacheRPCResponses, "CDRsV1.ProcessEvent:testID",
		&utils.CachedRPCResponse{Result: &rply, Error: nil},
		nil, true, utils.NonTransactional)

	err := newCDRSrv.V1ProcessEvent(context.Background(), cgrEv, &rply)
	if err != nil {
		t.Errorf("\nExpected <%+v> \n, received <%+v>", nil, err)
	}
	expected := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			utils.Cost: 123,
		},
	}
	if !reflect.DeepEqual(expected, cgrEv) {
		t.Errorf("\nExpected <%+v> \n,received <%+v>", expected, cgrEv)
	}
}

func TestCDRsV1ProcessEventWithGetCacheGet(t *testing.T) {
	testCache := engine.Cache
	tmpC := config.CgrConfig()
	defer func() {
		engine.Cache = testCache
		config.SetCgrConfig(tmpC)
	}()

	cfg := config.NewDefaultCGRConfig()
	cfg.CacheCfg().Partitions[utils.CacheRPCResponses].Limit = 1

	data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DbCfg().Items)
	dbCM := engine.NewDBConnManager(map[string]engine.DataDB{utils.MetaDefault: data}, cfg.DbCfg())
	dm := engine.NewDataManager(dbCM, cfg, nil)
	fltrs := engine.NewFilterS(cfg, nil, dm)
	engine.Cache = engine.NewCacheS(cfg, dm, nil, nil)
	newCDRSrv := NewCDRServer(cfg, dm, fltrs, nil)
	cgrEv := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			utils.Cost: 123,
		},
	}

	rply := []*utils.EventsWithOpts{}
	engine.Cache.Set(context.Background(), utils.CacheRPCResponses, "CDRsV1.ProcessEvent:testID",
		&utils.CachedRPCResponse{Result: &rply, Error: nil},
		nil, true, utils.NonTransactional)

	err := newCDRSrv.V1ProcessEventWithGet(context.Background(), cgrEv, &rply)
	if err != nil {
		t.Errorf("\nExpected <%+v> \n, received <%+v>", nil, err)
	}
	expected := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			utils.Cost: 123,
		},
		APIOpts: map[string]any{},
	}
	delete(cgrEv.APIOpts, utils.MetaCDRID) // ignore autogenerated *cdr field when comparing
	if !reflect.DeepEqual(expected, cgrEv) {
		t.Errorf("\nExpected <%+v> \n,received <%+v>", expected, cgrEv)
	}
}

func TestCDRsV1ProcessEventWithGetMockCacheErrResp(t *testing.T) {

	testCache := engine.Cache
	tmpC := config.CgrConfig()
	defer func() {
		engine.Cache = testCache
		config.SetCgrConfig(tmpC)
	}()
	engine.Cache.Clear(nil)

	cfg := config.NewDefaultCGRConfig()
	cfg.CacheCfg().Partitions[utils.CacheRPCResponses].Limit = 1
	config.SetCgrConfig(cfg)

	data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DbCfg().Items)
	dbCM := engine.NewDBConnManager(map[string]engine.DataDB{utils.MetaDefault: data}, cfg.DbCfg())
	dm := engine.NewDataManager(dbCM, cfg, nil)
	fltrs := engine.NewFilterS(cfg, nil, dm)
	engine.Cache = engine.NewCacheS(cfg, dm, nil, nil)
	newCDRSrv := NewCDRServer(cfg, dm, fltrs, nil)

	cgrEv := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "testID",
		Event: map[string]any{
			utils.Cost: 123,
		},
		APIOpts: map[string]any{},
	}

	evs := []*utils.EventsWithOpts{
		{
			Event: map[string]any{
				utils.Cost: 666,
			},
		},
	}
	engine.Cache.Set(context.Background(), utils.CacheRPCResponses, "CDRsV1.ProcessEventWithGet:testID",
		&utils.CachedRPCResponse{Result: &evs, Error: nil},
		nil, true, utils.NonTransactional)
	var reply []*utils.EventsWithOpts
	err := newCDRSrv.V1ProcessEventWithGet(context.Background(), cgrEv, &reply)
	if err != nil {
		t.Errorf("\nExpected <%+v> \n, received <%+v>", nil, err)
	}

	expectedVal := []*utils.EventsWithOpts{
		{
			Event: map[string]any{
				utils.Cost: 666,
			},
		},
	}
	if !reflect.DeepEqual(expectedVal, reply) {
		t.Errorf("Expected %v, received %v", utils.ToJSON(expectedVal), utils.ToJSON(reply))
	}
}

func TestCDRsV1ProcessStoredEvents(t *testing.T) {
	testCache := engine.Cache
	tmpC := config.CgrConfig()
	defer func() {
		engine.Cache = testCache
		config.SetCgrConfig(tmpC)
	}()

	cfg := config.NewDefaultCGRConfig()
	cfg.CdrsCfg().EEsConns = []string{utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs)}

	data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DbCfg().Items)
	connMng := engine.NewConnManager(cfg)
	dbCM := engine.NewDBConnManager(map[string]engine.DataDB{utils.MetaDefault: data}, cfg.DbCfg())
	dm := engine.NewDataManager(dbCM, cfg, nil)
	fltrs := engine.NewFilterS(cfg, nil, dm)
	engine.Cache = engine.NewCacheS(cfg, dm, nil, nil)
	newCDRSrv := NewCDRServer(cfg, dm, fltrs, connMng)
	ccM := &ccMock{
		calls: map[string]func(ctx *context.Context, args any, reply any) error{
			utils.EeSv1ProcessEvent: func(ctx *context.Context, args, reply any) error {
				*reply.(*map[string]map[string]any) = map[string]map[string]any{}
				return nil
			},
		},
	}
	rpcInternal := make(chan birpc.ClientConnector, 1)
	rpcInternal <- ccM
	newCDRSrv.connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs), utils.ThresholdSv1, rpcInternal)

	testCGREvent := &utils.CGREvent{
		Tenant: "cgrates.org",
		ID:     "test-cgrid-1",
		Event: map[string]any{
			"CGRID":       "test-cgrid-1",
			"Tenant":      "cgrates.org",
			"Category":    "call",
			"Account":     "1001",
			"Destination": "1002",
			"SetupTime":   time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC),
			"AnswerTime":  time.Date(2024, 1, 1, 10, 0, 5, 0, time.UTC),
			"Usage":       60 * time.Second,
			"Cost":        1.5,
		},
	}

	ctx := context.Background()
	err := dm.SetCDR(ctx, testCGREvent, false)
	if err != nil {
		t.Fatalf("Failed to set CDR: %v", err)
	}

	args := &utils.CDRFilters{
		Tenant: "cgrates.org",
	}
	var reply string
	err = newCDRSrv.V1ProcessStoredEvents(context.Background(), args, &reply)
	if err != nil {
		t.Errorf("Expected no error, got: %v", err)
	}
	if reply != utils.OK {
		t.Errorf("Expected reply to be %s, got: %s", utils.OK, reply)
	}
	if args.ID == utils.EmptyString {
		t.Error("Expected args.ID to be set")
	}
}

func TestCDRsV1ProcessStoredEventsWithEmptyArgs(t *testing.T) {
	testCache := engine.Cache
	tmpC := config.CgrConfig()
	defer func() {
		engine.Cache = testCache
		config.SetCgrConfig(tmpC)
	}()

	cfg := config.NewDefaultCGRConfig()
	cfg.CdrsCfg().EEsConns = []string{utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs)}

	data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DbCfg().Items)
	connMng := engine.NewConnManager(cfg)
	dbCM := engine.NewDBConnManager(map[string]engine.DataDB{utils.MetaDefault: data}, cfg.DbCfg())
	dm := engine.NewDataManager(dbCM, cfg, nil)
	fltrs := engine.NewFilterS(cfg, nil, dm)
	engine.Cache = engine.NewCacheS(cfg, dm, nil, nil)
	newCDRSrv := NewCDRServer(cfg, dm, fltrs, connMng)

	ccM := &ccMock{
		calls: map[string]func(ctx *context.Context, args any, reply any) error{
			utils.EeSv1ProcessEvent: func(ctx *context.Context, args, reply any) error {
				*reply.(*map[string]map[string]any) = map[string]map[string]any{}
				return nil
			},
		},
	}
	rpcInternal := make(chan birpc.ClientConnector, 1)
	rpcInternal <- ccM
	newCDRSrv.connMgr.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal,
		utils.MetaEEs), utils.ThresholdSv1, rpcInternal)

	testCGREvent := &utils.CGREvent{
		Tenant: cfg.GeneralCfg().DefaultTenant,
		ID:     "test-cgrid-empty-args",
		Event: map[string]any{
			"CGRID":       "test-cgrid-empty-args",
			"Tenant":      cfg.GeneralCfg().DefaultTenant,
			"Category":    "call",
			"Account":     "1001",
			"Destination": "1002",
			"SetupTime":   time.Date(2024, 1, 1, 10, 0, 0, 0, time.UTC),
			"AnswerTime":  time.Date(2024, 1, 1, 10, 0, 5, 0, time.UTC),
			"Usage":       60 * time.Second,
			"Cost":        1.5,
		},
	}

	ctx := context.Background()
	err := dm.SetCDR(ctx, testCGREvent, false)
	if err != nil {
		t.Fatalf("Failed to set CDR: %v", err)
	}

	args := &utils.CDRFilters{}
	var reply string
	err = newCDRSrv.V1ProcessStoredEvents(context.Background(), args, &reply)
	if err != nil {
		t.Errorf("Expected no error, got: %v", err)
	}
	if reply != utils.OK {
		t.Errorf("Expected reply to be %s, got: %s", utils.OK, reply)
	}
	if args.ID == utils.EmptyString {
		t.Error("Expected args.ID to be generated")
	}
	if args.Tenant != cfg.GeneralCfg().DefaultTenant {
		t.Errorf("Expected args.Tenant to be %s, got: %s", cfg.GeneralCfg().DefaultTenant, args.Tenant)
	}
}
