package fiko_socket_io

import (
	"context"
	"log"
	"os"
	"reflect"
	"sync"

	"server/apps/cmm"
	"server/apps/fikoyt_api/ajanlar"
	"server/apps/fikoyt_api/collab"
	uyar "server/apps/uyar_dokum/uyar"
	fiko_mongo "server/sistem/fikoyt_mongo"
	"server/sistem/fikoyt_ortak"
	socket_ortak "server/sistem/socket_ortak"
	"time"

	"github.com/gofiber/fiber/v3"
	"github.com/gofiber/fiber/v3/middleware/adaptor"
	"github.com/redis/go-redis/v9"
	EIOLog "github.com/zishang520/engine.io/v2/log"
	"github.com/zishang520/engine.io/v2/types"
	redis_adapter "github.com/zishang520/socket.io-go-redis/adapter"
	redis_types "github.com/zishang520/socket.io-go-redis/types"
	"github.com/zishang520/socket.io/v2/socket"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo/options"
)

// var FikoSocketIo *socket.Server

// Cihaz son kart durumlarini hafizada tut (sayfa yenilenince sorgulanabilsin)
var cihazSonDurum = make(map[string]map[string]interface{})
var cihazSonDurumMu sync.RWMutex

// Socket ID -> cihaz_kimlik eslestirmesi (disconnect'te cihazi bulmak icin)
var soketCihazMap = make(map[string]string)
var soketCihazMapMu sync.RWMutex

// Bagli cihaz bilgileri (cihaz_kimlik -> bilgi map)
var bagliCihazBilgi = make(map[string]map[string]interface{})
var bagliCihazBilgiMu sync.RWMutex

// Cihaz telemetri verileri (cihaz_kimlik -> son telemetri)
var cihazTelemetri = make(map[string]map[string]interface{})
var cihazTelemetriMu sync.RWMutex

func Ayarla(app *fiber.App) {
	baglantilariSil()
	EIOLog.DEBUG = true
	socketioSettings := socket.DefaultServerOptions()
	socketioSettings.SetServeClient(true)
	// c.SetConnectionStateRecovery(&socket.ConnectionStateRecovery{})
	socketioSettings.SetAllowEIO3(true)
	socketioSettings.SetAllowUpgrades(true)
	socketioSettings.SetTransports(types.NewSet("polling", "websocket", "webtransport"))

	socketioSettings.SetPingInterval(25000 * time.Millisecond) // 25 saniye
	socketioSettings.SetPingTimeout(20000 * time.Millisecond)  // 20 saniye
	socketioSettings.SetMaxHttpBufferSize(1000000)
	socketioSettings.SetConnectTimeout(15000 * time.Millisecond)
	socketioSettings.SetCors(&types.Cors{
		Origin:      "*",
		Credentials: true,
	})

	// Redis Adapter ayarları (Prefork için gerekli)
	redisHost := os.Getenv("REDIS_HOST")
	if redisHost == "" {
		redisHost = "redis"
	}
	redisPort := os.Getenv("REDIS_PORT")
	if redisPort == "" {
		redisPort = "6379"
	}

	// Redis bağlantısını test et
	redisGoClient := redis.NewClient(&redis.Options{
		Addr: redisHost + ":" + redisPort,
	})

	// Ping ile bağlantıyı kontrol et
	_, redisErr := redisGoClient.Ping(context.Background()).Result()
	if redisErr != nil {
		log.Printf("UYARI: Redis baglantisi basarisiz (%s:%s): %v - Adapter olmadan devam ediliyor", redisHost, redisPort, redisErr)
	} else {
		redisClient := redis_types.NewRedisClient(context.Background(), redisGoClient)
		adapterBuilder := &redis_adapter.RedisAdapterBuilder{
			Redis: redisClient,
			Opts:  &redis_adapter.RedisAdapterOptions{},
		}
		socketioSettings.SetAdapter(adapterBuilder)
		log.Printf("Socket.IO Redis Adapter ayarlandi: %s:%s", redisHost, redisPort)
	}

	socket_ortak.FikoSocketIo = socket.NewServer(nil, socketioSettings)

	socket_ortak.FikoSocketIo.On("connection", func(clients ...interface{}) {
		client := clients[0].(*socket.Socket)

		clientId := string(client.Id())
		hdrs := client.Handshake().Headers
		var cihazHeader, userAgent string
		if v, ok := hdrs["Cihaz_kimlik"]; ok && len(v) > 0 { cihazHeader = v[0] }
		if v, ok := hdrs["User-Agent"]; ok && len(v) > 0 { userAgent = v[0] }
		log.Printf("[SOCKET] Yeni baglanti: %s | Cihaz: %s | UA: %s", clientId, cihazHeader, userAgent)

		ClientBaglandi(client)
	})

	//
	app.Get("/socket.io/", adaptor.HTTPHandler(socket_ortak.FikoSocketIo.ServeHandler(socketioSettings)))
	app.Post("/socket.io/", adaptor.HTTPHandler(socket_ortak.FikoSocketIo.ServeHandler(socketioSettings)))

	// FikoSocketIo.Use(func(socket *socket.Socket, next func(*socket.ExtendedError)) {
	// 	fmt.Println(socket.Request().Headers())
	// 	next(nil)
	// })
	// FikoSocketIo.FetchSockets()
}

// hasKey kontrol fonksiyonu
func hasKey(data interface{}, key string) bool {
	if reflect.TypeOf(data).Kind() == reflect.Map {
		return reflect.ValueOf(data).MapIndex(reflect.ValueOf(key)).IsValid()
	}
	return false
}

func ClientBaglandi(client *socket.Socket) {
	// FikoYT Ajan Sistemi eventlerini kaydet
	ajanlar.AjanSocketEventleriKaydet(client)

	// CMM (Canlı Tarama) eventlerini kaydet
	cmm.CMMSocketEventleriKaydet(client)

	// CAD Real-Time Collaboration eventlerini kaydet
	collab.CollabSocketEventleriKaydet(client)

	// Bildirim sistemi eventlerini kaydet
	uyar.BildirimSocketEventKaydet(client)

	client.On("disconnect", func(args ...interface{}) {
		ctx := context.TODO()
		clientId := string(client.Id())

		var k = fikoyt_ortak.YeniSoketten(clientId)

		collectionGoSoketler := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("goSoketler")

		soketSorgu := bson.M{
			"soket": clientId,
		}

		_, err := collectionGoSoketler.DeleteMany(ctx, soketSorgu)
		if err != nil {
			log.Printf("Soket silme hatası: %v", err)
		}

		if k != nil {
			k.OlayYolla("FikoYT.sistem.cihaz.bağlandı.toplamlar", k.AktifCihazlar())
		}

		// Cihaz (kart okuyucu vb.) disconnect olduysa diger client'lara bildir
		soketCihazMapMu.Lock()
		cihazKimlik, eslesmisVar := soketCihazMap[clientId]
		if eslesmisVar {
			delete(soketCihazMap, clientId)
		}
		soketCihazMapMu.Unlock()

		if eslesmisVar && cihazKimlik != "" {
			// Hafizadaki kart durumunu temizle
			cihazSonDurumMu.Lock()
			delete(cihazSonDurum, cihazKimlik)
			cihazSonDurumMu.Unlock()

			// Bagli cihaz bilgisi ve telemetri temizle
			bagliCihazBilgiMu.Lock()
			delete(bagliCihazBilgi, cihazKimlik)
			bagliCihazBilgiMu.Unlock()

			cihazTelemetriMu.Lock()
			delete(cihazTelemetri, cihazKimlik)
			cihazTelemetriMu.Unlock()

			// MongoDB'de cevrimiciMi = false yap
			go cihazCevrimiciGuncelle(cihazKimlik, false)

			// Diger client'lara cihaz koptu bildirimi
			if socket_ortak.FikoSocketIo != nil {
				koptuData := map[string]interface{}{
					"cihaz_kimlik": cihazKimlik,
					"durum":        "koptu",
				}
				socket_ortak.FikoSocketIo.FetchSockets()(func(sockets []*socket.RemoteSocket, err error) {
					if err != nil {
						return
					}
					for _, s := range sockets {
						if string(s.Id()) != clientId {
							s.Emit("FikoYT.sistem.io.cihaz.koptu", koptuData)
						}
					}
				})
			}
			log.Printf("Cihaz koptu: %s (socketId: %s)", cihazKimlik, clientId)
		}
	})
	/**/
	client.On("FikoYT.sistem.io.cihaz.baglandi", func(args ...interface{}) {
		// Eski format uyumlulugu: FikoYT key'li data varsa soketBaglandi cagir
		if len(args) >= 2 {
			if receivedData, ok := args[len(args)-2].(map[string]interface{}); ok {
				if _, hasFikoYT := receivedData["FikoYT"]; hasFikoYT {
					soketBaglandi(string(client.Id()), receivedData)
				}
			}
		}

		// Cihaz kimlik eslestirmesini kaydet + bagli cihaz bilgisini sakla + broadcast
		if len(args) > 0 {
			if data, ok := args[0].(map[string]interface{}); ok {
				if ck, ok := data["cihaz_kimlik"].(string); ok && ck != "" {
					soketCihazMapMu.Lock()
					soketCihazMap[string(client.Id())] = ck
					soketCihazMapMu.Unlock()

					// Bagli cihaz bilgisini kaydet
					bagliCihazBilgiMu.Lock()
					bagliCihazBilgi[ck] = data
					bagliCihazBilgiMu.Unlock()

					log.Printf("Cihaz baglandi: %s (tur: %v, socketId: %s)", ck, data["tur"], string(client.Id()))

					// cihaz_db_id varsa, DB'deki cihazKimlik'i gercek kimlikle senkronize et
					if dbId, ok := data["cihaz_db_id"].(string); ok && dbId != "" {
						go cihazKimlikSenkronize(dbId, ck)
					}

					// MongoDB'de cevrimiciMi = true yap
					go cihazCevrimiciGuncelle(ck, true)

					// Diger client'lara broadcast
					if socket_ortak.FikoSocketIo != nil {
						senderID := string(client.Id())
						socket_ortak.FikoSocketIo.FetchSockets()(func(sockets []*socket.RemoteSocket, err error) {
							if err != nil {
								return
							}
							for _, s := range sockets {
								if string(s.Id()) != senderID {
									s.Emit("FikoYT.sistem.io.cihaz.baglandi", data)
								}
							}
						})
					}
				}
			}
		}
	})
	/**/
	// Kart okuyucu vb. cihaz guncelleme olaylarini diger client'lara ilet + hafizada tut
	client.On("FikoYT.sistem.io.cihaz.guncellendi", func(args ...interface{}) {
		if len(args) < 1 {
			return
		}
		firstArg := args[0]

		// Son durumu hafizada sakla + socket-cihaz eslestir
		if data, ok := firstArg.(map[string]interface{}); ok {
			if cihazKimlik, ok := data["cihaz_kimlik"].(string); ok && cihazKimlik != "" {
				data["_kayit_zamani"] = time.Now().Unix()
				cihazSonDurumMu.Lock()
				cihazSonDurum[cihazKimlik] = data
				cihazSonDurumMu.Unlock()
				soketCihazMapMu.Lock()
				soketCihazMap[string(client.Id())] = cihazKimlik
				soketCihazMapMu.Unlock()

				// kart_kimlik veya durum alanı varsa tetikleyici motoru bilgilendir
				durum, _ := data["durum"].(string)
				if durum != "" {
					// Kart koyuldu/cekildi olayini MongoDB'ye kaydet (pdks_kart_hareketler)
					go func(kayit map[string]interface{}) {
						ctx := context.TODO()
						delete(kayit, "_kayit_zamani")
						kayit["sunucu_zamani"] = time.Now().Format(time.RFC3339)
						kayit["vt"] = "FikoYT.sistem.cihaz.olaylar"
						_, err := fiko_mongo.GetMongoDBClient().Database("fikoyt").
							Collection("pdks_kart_hareketler").InsertOne(ctx, kayit)
						if err != nil {
							log.Printf("Kart hareket kayit hatasi: %v", err)
						}
					}(data)

					go uyar.TetikleyiciMotorOrnek.OlayIsle(data)
				}
			}
		}

		// Diger client'lara broadcast
		if socket_ortak.FikoSocketIo != nil {
			senderID := string(client.Id())
			socket_ortak.FikoSocketIo.FetchSockets()(func(sockets []*socket.RemoteSocket, err error) {
				if err != nil {
					return
				}
				for _, s := range sockets {
					if string(s.Id()) != senderID {
						s.Emit("FikoYT.sistem.io.cihaz.guncellendi", firstArg)
					}
				}
			})
		}
	})

	// Client kart durumunu sorgulayabilir (sayfa yenilendiginde)
	client.On("FikoYT.sistem.io.cihaz.durum-sorgula", func(args ...interface{}) {
		cihazKimlik := ""
		if len(args) > 0 {
			if data, ok := args[0].(map[string]interface{}); ok {
				cihazKimlik, _ = data["cihaz_kimlik"].(string)
			}
		}

		cihazSonDurumMu.RLock()
		defer cihazSonDurumMu.RUnlock()

		if cihazKimlik != "" {
			// Belirli cihazin durumunu don — kart_uptime_sn'yi anlik guncelle
			if durum, ok := cihazSonDurum[cihazKimlik]; ok {
				kopya := make(map[string]interface{})
				for k, v := range durum {
					kopya[k] = v
				}
				if kz, ok := kopya["_kayit_zamani"].(int64); ok {
					gecenSn := time.Now().Unix() - kz
					if ut, ok := kopya["kart_uptime_sn"].(float64); ok {
						kopya["kart_uptime_sn"] = ut + float64(gecenSn)
					}
				}
				delete(kopya, "_kayit_zamani")
				client.Emit("FikoYT.sistem.io.cihaz.durum-cevap", kopya)
			} else {
				client.Emit("FikoYT.sistem.io.cihaz.durum-cevap", map[string]interface{}{
					"cihaz_kimlik": cihazKimlik,
					"kart_kimlik":  "",
				})
			}
		} else {
			// Tum cihazlarin durumunu don — kart_uptime_sn anlik guncelle
			tumDurum := make([]interface{}, 0, len(cihazSonDurum))
			for _, d := range cihazSonDurum {
				kopya := make(map[string]interface{})
				for k, v := range d {
					kopya[k] = v
				}
				if kz, ok := kopya["_kayit_zamani"].(int64); ok {
					gecenSn := time.Now().Unix() - kz
					if ut, ok := kopya["kart_uptime_sn"].(float64); ok {
						kopya["kart_uptime_sn"] = ut + float64(gecenSn)
					}
				}
				delete(kopya, "_kayit_zamani")
				tumDurum = append(tumDurum, kopya)
			}
			client.Emit("FikoYT.sistem.io.cihaz.durum-cevap", tumDurum)
		}
	})

	// Telemetri verisini kaydet + diger client'lara ilet
	client.On("FikoYT.sistem.io.cihaz.telemetri", func(args ...interface{}) {
		if len(args) < 1 {
			return
		}
		data, ok := args[0].(map[string]interface{})
		if !ok {
			return
		}
		ck, _ := data["cihaz_kimlik"].(string)
		if ck == "" {
			return
		}

		// Telemetri verisini kaydet
		cihazTelemetriMu.Lock()
		cihazTelemetri[ck] = data
		cihazTelemetriMu.Unlock()

		// Socket-cihaz eslestirmesini guncelle
		soketCihazMapMu.Lock()
		soketCihazMap[string(client.Id())] = ck
		soketCihazMapMu.Unlock()

		// Bagli cihaz bilgisini guncelle (yoksa ekle)
		bagliCihazBilgiMu.Lock()
		ilkTelemetri := bagliCihazBilgi[ck] == nil
		if ilkTelemetri {
			bagliCihazBilgi[ck] = map[string]interface{}{
				"cihaz_kimlik":    ck,
				"cihaz_ismi":      data["cihaz_ismi"],
				"tur":             "hmi_pano",
				"baglanti_zamani": time.Now().Format(time.RFC3339),
			}
		}
		bagliCihazBilgiMu.Unlock()

		// Ilk telemetride cevrimici yap (baglandi eventi gelmemis olabilir)
		if ilkTelemetri {
			go cihazCevrimiciGuncelle(ck, true)
		}

		// Diger client'lara broadcast
		if socket_ortak.FikoSocketIo != nil {
			senderID := string(client.Id())
			socket_ortak.FikoSocketIo.FetchSockets()(func(sockets []*socket.RemoteSocket, err error) {
				if err != nil {
					return
				}
				for _, s := range sockets {
					if string(s.Id()) != senderID {
						s.Emit("FikoYT.sistem.io.cihaz.telemetri", data)
					}
				}
			})
		}
	})

	// Bagli cihaz listesini sorgula
	client.On("FikoYT.sistem.io.cihaz.liste-sorgula", func(args ...interface{}) {
		bagliCihazBilgiMu.RLock()
		defer bagliCihazBilgiMu.RUnlock()

		liste := make([]interface{}, 0, len(bagliCihazBilgi))
		for _, bilgi := range bagliCihazBilgi {
			liste = append(liste, bilgi)
		}

		client.Emit("FikoYT.sistem.io.cihaz.liste-cevap", map[string]interface{}{
			"liste": liste,
		})
	})

	// Telemetri durumunu sorgula
	client.On("FikoYT.sistem.io.cihaz.telemetri-sorgula", func(args ...interface{}) {
		cihazTelemetriMu.RLock()
		defer cihazTelemetriMu.RUnlock()

		// Belirli bir cihaz mi yoksa tumu mu
		cihazKimlik := ""
		if len(args) > 0 {
			if data, ok := args[0].(map[string]interface{}); ok {
				cihazKimlik, _ = data["cihaz_kimlik"].(string)
			}
		}

		if cihazKimlik != "" {
			if t, ok := cihazTelemetri[cihazKimlik]; ok {
				client.Emit("FikoYT.sistem.io.cihaz.telemetri", t)
			}
		} else {
			for _, t := range cihazTelemetri {
				client.Emit("FikoYT.sistem.io.cihaz.telemetri", t)
			}
		}
	})

	// Uzak komut: admin panelden belirli cihaza komut ilet
	client.On("FikoYT.sistem.io.cihaz.komut", func(args ...interface{}) {
		if len(args) < 1 {
			return
		}
		data, ok := args[0].(map[string]interface{})
		if !ok {
			return
		}
		hedefCihazKimlik, _ := data["cihaz_kimlik"].(string)
		if hedefCihazKimlik == "" {
			return
		}

		// Hedef cihazin soket ID'sini bul
		soketCihazMapMu.RLock()
		var hedefSoketId string
		for sid, ck := range soketCihazMap {
			if ck == hedefCihazKimlik {
				hedefSoketId = sid
				break
			}
		}
		soketCihazMapMu.RUnlock()

		if hedefSoketId != "" {
			// Hedef cihaza dogrudan gonder
			if socket_ortak.FikoSocketIo != nil {
				socket_ortak.FikoSocketIo.FetchSockets()(func(sockets []*socket.RemoteSocket, err error) {
					if err != nil {
						return
					}
					for _, s := range sockets {
						if string(s.Id()) == hedefSoketId {
							s.Emit("FikoYT.sistem.io.cihaz.komut", data)
							break
						}
					}
				})
			}
			log.Printf("Komut gonderildi: %s -> %s (komut: %v)", string(client.Id()), hedefCihazKimlik, data["komut_kodu"])
		} else {
			log.Printf("Komut hedefi bulunamadi: %s", hedefCihazKimlik)
		}
	})

	// Cihaz olay kaydi: cihazlardan gelen olaylari DB'ye kaydet + broadcast
	client.On("FikoYT.sistem.io.cihaz.olay", func(args ...interface{}) {
		if len(args) < 1 {
			return
		}
		data, ok := args[0].(map[string]interface{})
		if !ok {
			return
		}

		// cihaz_kimlik yoksa socket eslesmesinden otomatik ekle
		ckMevcut, _ := data["cihaz_kimlik"].(string)
		if ckMevcut == "" {
			soketCihazMapMu.RLock()
			if eslesen, var_ := soketCihazMap[string(client.Id())]; var_ {
				data["cihaz_kimlik"] = eslesen
			}
			soketCihazMapMu.RUnlock()
		}

		// Zaman damgasi ekle
		data["sunucu_zamani"] = time.Now().Format(time.RFC3339)

		// MongoDB'ye kaydet
		go func() {
			ctx := context.TODO()
			collection := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
			data["vt"] = "FikoYT.sistem.cihaz.olaylar"
			_, err := collection.InsertOne(ctx, data)
			if err != nil {
				log.Printf("Cihaz olay kayit hatasi: %v", err)
			}
		}()

		// Diger client'lara broadcast (admin paneller gorecek)
		if socket_ortak.FikoSocketIo != nil {
			senderID := string(client.Id())
			socket_ortak.FikoSocketIo.FetchSockets()(func(sockets []*socket.RemoteSocket, err error) {
				if err != nil {
					return
				}
				for _, s := range sockets {
					if string(s.Id()) != senderID {
						s.Emit("FikoYT.sistem.io.cihaz.olay", data)
					}
				}
			})
		}

		ck, _ := data["cihaz_kimlik"].(string)
		olayKodu, _ := data["olay_kodu"].(string)
		log.Printf("Cihaz olay: %s -> %s", ck, olayKodu)

		go uyar.TetikleyiciMotorOrnek.OlayIsle(data)
	})

	// Komut cevabi: cihazdan gelen cevabi admin panele ilet + DB'ye kaydet
	client.On("FikoYT.sistem.io.cihaz.komut-cevap", func(args ...interface{}) {
		if len(args) < 1 {
			return
		}

		// DB'ye cevabi kaydet
		if data, ok := args[0].(map[string]interface{}); ok {
			data["sunucu_zamani"] = time.Now().Format(time.RFC3339)
			go func() {
				ctx := context.TODO()
				// Komut gecmisine cevabi ekle
				komutId, _ := data["komut_id"].(string)
				if komutId != "" {
					collection := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("cihaz_komutlar")
					oid, err := primitive.ObjectIDFromHex(komutId)
					if err == nil {
						durum, _ := data["durum"].(string)
						if durum == "" {
							basarili, _ := data["basarili"].(bool)
							if basarili {
								durum = "tamamlandi"
							} else {
								durum = "hata"
							}
						}
						guncelleme := bson.M{
							"$set": bson.M{
								"durum":           durum,
								"cevap":           data,
								"tamamlanmaTarihi": time.Now().Format(time.RFC3339),
							},
						}
						collection.UpdateByID(ctx, oid, guncelleme)
					}
				}
			}()
		}

		// Tum dinleyicilere broadcast (admin paneller alacak)
		if socket_ortak.FikoSocketIo != nil {
			senderID := string(client.Id())
			socket_ortak.FikoSocketIo.FetchSockets()(func(sockets []*socket.RemoteSocket, err error) {
				if err != nil {
					return
				}
				for _, s := range sockets {
					if string(s.Id()) != senderID {
						s.Emit("FikoYT.sistem.io.cihaz.komut-cevap", args[0])
					}
				}
			})
		}
	})
}

/**/
func baglantilariSil() {
	collectionBaglantilar := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")

	// İlk sorgu: "FikoYT.sistem.io.cihaz.baglantilar" verisini sil
	// sorgu := bson.M{
	// 	"vt": "FikoYT.sistem.io.cihaz.baglantilar",
	// }

	// _, err := collectionBaglantilar.DeleteMany(context.TODO(), sorgu)
	// if err != nil {
	// 	log.Fatalf("DeleteMany error: %v", err)
	// 	return
	// }

	// İkinci sorgu: "FikoYT.sistem.io.cihazlar.cihaz" verisini güncelle
	sorgu := bson.M{
		"vt": "FikoYT.sistem.io.cihazlar.cihaz",
	}

	// UpdateMany işlemi, info.sockets'ı boş bir dizi olarak ayarlar
	update := bson.M{
		"$set": bson.M{
			"veri.soketler": []interface{}{},
		},
	}

	collectionBaglantilar.UpdateMany(context.TODO(), sorgu, update, options.Update().SetUpsert(false))

	collectionGoSoketler := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("goSoketler")

	collectionGoSoketler.DeleteMany(context.TODO(), bson.M{})

	// Sunucu restart'inda tum cihazlari offline yap
	collectionBaglantilar.UpdateMany(context.TODO(),
		bson.M{"vt": "FikoYT.sistem.cihazlar", "cevrimiciMi": true},
		bson.M{"$set": bson.M{"cevrimiciMi": false}},
	)
}

/**/
func soketBaglandi(clientID string, receivedData map[string]interface{}) {
	// MongoDB bağlamı ve koleksiyonu
	ctx := context.TODO()
	dbClient := fiko_mongo.GetMongoDBClient() // MongoDB bağlantısını döndüren varsayımsal bir fonksiyon.
	// collectionHareketler := dbClient.Database("fikoyt").Collection("hareketler")
	/** NOT:  Yeni Bağlantı kaydı */
	collectionGoCihazlar := dbClient.Database("fikoyt").Collection("goCihazlar")

	cihazMap, ok := receivedData["FikoYT"].(map[string]interface{})
	if !ok {
		log.Println("Hata: receivedData['FikoYT'] beklenen formatta değil.")
		return
	}

	cihazKimlikStr, ok := cihazMap["cihaz_kimlik"].(string)
	if !ok {
		log.Println("Hata: cihaz_kimlik string değil.")
		return
	}

	cihazKimlik, err := primitive.ObjectIDFromHex(cihazKimlikStr)
	if err != nil {
		log.Printf("Hata: Geçersiz ObjectID (%v): %v\n", cihazKimlikStr, err)
		// return
	} else {
		cihazSorgu := bson.M{
			"kimlik": cihazKimlik,
		}

		cihazKayit := bson.M{
			"tarih":    time.Now(),
			"kimlik":   cihazKimlik,
			"tipi":     cihazMap["cihaz_tipi"],
			"bilgiler": cihazMap["cihaz_bilgi"],
			// "soket": clientID, // eğer gerekiyorsa aktif hale getir
		}

		_, erSr := collectionGoCihazlar.UpdateMany(ctx, cihazSorgu, bson.M{
			"$set": cihazKayit,
		}, options.Update().SetUpsert(true))
		if erSr != nil {
			log.Printf(" error: %v\n", erSr)
			// return
		}
	}

	/** NOT:  Soketler */
	collectionGoSoketler := dbClient.Database("fikoyt").Collection("goSoketler")
	soketSorgu := bson.M{
		"soket": clientID,
		"cihaz": cihazKimlik,
	}

	soketKayit := bson.M{
		"tarih": time.Now(),
		"soket": clientID,
		"cihaz": cihazKimlik,
		// "soket": clientID, // eğer gerekiyorsa aktif hale getir
	}
	/***/
	kullaniciKimlikStr, ok := receivedData["FikoYT"].(map[string]interface{})["kullanici_kimlik"].(string)
	if !ok {
		// log.Println("Hata: Kullanıcı kimlik bilgisi alınamadı")
		// return
	}

	kullaniciKimlik, err := primitive.ObjectIDFromHex(kullaniciKimlikStr)
	if err != nil {
		// log.Printf("Hata: Geçersiz Kullanıcı ObjectID (%v): %v\n", kullaniciKimlikStr, err)
		// return
		soketKayit["kullanici"] = nil

	} else {
		soketKayit["kullanici"] = kullaniciKimlik

	}

	/***/
	_, erS := collectionGoSoketler.ReplaceOne(ctx, soketSorgu, soketKayit, options.Replace().SetUpsert(true))
	if erS != nil {
		log.Printf("error: %v\n", erS)
		// return
	}

	var k = fikoyt_ortak.YeniSoketten(clientID)

	if k == nil {
		return
	}
	// fmt.Print(len(k.Soketler()))
	k.OlayYolla("FikoYT.sistem.cihaz.bağlandı.toplamlar", k.AktifCihazlar())

}

func cihazKimlikSenkronize(dbId string, gercekKimlik string) {
	oid, err := primitive.ObjectIDFromHex(dbId)
	if err != nil {
		return
	}
	collection := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	sonuc, err := collection.UpdateOne(
		context.TODO(),
		bson.M{"_id": oid, "vt": "FikoYT.sistem.cihazlar", "cihazKimlik": bson.M{"$ne": gercekKimlik}},
		bson.M{"$set": bson.M{"cihazKimlik": gercekKimlik}},
	)
	if err != nil {
		log.Printf("Cihaz kimlik senkronize hatasi (%s): %v", dbId, err)
	} else if sonuc.ModifiedCount > 0 {
		log.Printf("Cihaz kimlik senkronize: DB %s -> %s", dbId, gercekKimlik)
	}
}

func cihazCevrimiciGuncelle(cihazKimlik string, cevrimici bool) {
	collection := fiko_mongo.GetMongoDBClient().Database("fikoyt").Collection("hareketler")
	guncelleme := bson.M{
		"$set": bson.M{
			"cevrimiciMi": cevrimici,
		},
	}
	if cevrimici {
		guncelleme["$set"].(bson.M)["sonBaglantiZamani"] = time.Now()
	}
	_, err := collection.UpdateOne(
		context.TODO(),
		bson.M{"vt": "FikoYT.sistem.cihazlar", "cihazKimlik": cihazKimlik},
		guncelleme,
	)
	if err != nil {
		log.Printf("Cihaz cevrimici guncelleme hatasi (%s): %v", cihazKimlik, err)
	} else {
		durum := "cevrimdisi"
		if cevrimici {
			durum = "cevrimici"
		}
		log.Printf("Cihaz %s -> %s", cihazKimlik, durum)
	}
}

/**/
