package fiko_socket_io

import (
	"reflect"
	"time"

	"github.com/gofiber/fiber/v3"
	"github.com/gofiber/fiber/v3/middleware/adaptor"
	EIOLog "github.com/zishang520/engine.io/v2/log"
	"github.com/zishang520/engine.io/v2/types"
	"github.com/zishang520/socket.io/v2/socket"
)

var FikoSocketIo *socket.Server

func Ayarla(app *fiber.App) {
	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(2000 * time.Millisecond)
	socketioSettings.SetPingTimeout(2000 * time.Millisecond)
	socketioSettings.SetMaxHttpBufferSize(1000000)
	socketioSettings.SetConnectTimeout(3000 * time.Millisecond)
	socketioSettings.SetCors(&types.Cors{
		Origin:      "*",
		Credentials: true,
	})
	FikoSocketIo = socket.NewServer(nil, nil)

	FikoSocketIo.On("connection", func(clients ...interface{}) {
		client := clients[0].(*socket.Socket)

		// fmt.Println(clients...)
		client.Use(func(a []any, next func(error)) {
			//  delete(a[0].(map[string]interface{}), "deviceUuid")

			// fmt.Println("Burada----->", a[1])
			// if reflect.TypeOf(a[len(a)-2]).Kind() == reflect.Map {
			// 	if hasKey(a[1], "FikoYT") {
			// 		fmt.Println("Burada----->", a[1], len(a))
			// 		if reflect.TypeOf(a[len(a)-2]).Kind() != reflect.Map || !reflect.ValueOf(a[len(a)-2]).MapIndex(reflect.ValueOf("FikoYT")).IsValid() {
			// 			// Yeni bir map ekle
			// 			a[len(a)-2] = FikoYTMap.FikoYTMap{"FikoYT": FikoYTMap.FikoYTMap{"kid": nil, "cihaz_kimlik": nil}}
			// 			// a = append(a[:1], a[2:]...)
			// 		}
			// 		//
			// 	}
			// }
			a = ensureSecondLastIncludesFikoYTMap(a)

			next(nil)
		})
		ClientBaglandi(client)
	})

	//
	app.Get("/socket.io/", adaptor.HTTPHandler(FikoSocketIo.ServeHandler(socketioSettings)))
	app.Post("/socket.io/", adaptor.HTTPHandler(FikoSocketIo.ServeHandler(socketioSettings)))

	// FikoSocketIo.Use(func(socket *socket.Socket, next func(*socket.ExtendedError)) {
	// 	fmt.Println(socket.Request().Headers())
	// 	next(nil)
	// })
	// FikoSocketIo.FetchSockets()
}

func ensureSecondLastIncludesFikoYTMap(data []interface{}) []interface{} {
	// Eğer array boşsa, ilk eleman olarak nil ekleyelim
	if len(data) == 0 {
		data = append(data, nil)
		data = append(data, map[string]interface{}{"FikoYT": map[string]interface{}{"kid": nil, "cihaz_kimlik": nil}})
		data = append(data, nil) // Sonuna da bir nil ekleyelim
		return data
	}

	// Array'in uzunluğu 1'den küçükse, başa nil ekleyelim ve FikoYT map'i ekleyelim
	if len(data) < 2 {
		data = append(data, nil)
		data = append(data, map[string]interface{}{"FikoYT": map[string]interface{}{"kid": nil, "cihaz_kimlik": nil}})
		data = append(data, nil) // Sonuna da bir nil ekleyelim
		return data
	}

	// Sondan ikinci eleman
	secondLast := data[len(data)-2]

	// Eğer sondan ikinci eleman bir map değilse, ona yeni bir FikoYT map'i ekleyelim
	if reflect.TypeOf(secondLast).Kind() != reflect.Map {
		// Eğer sondan ikinci eleman map değilse, onu değiştirelim
		data = append(data, nil) // Sonuna bir nil ekleyelim
		data = append(data, map[string]interface{}{"FikoYT": map[string]interface{}{"kid": nil, "cihaz_kimlik": nil}})
		return data
	}

	// Eğer sondan ikinci eleman bir map ise, "FikoYT" anahtarını kontrol edelim
	secondLastMap := secondLast.(map[string]interface{})
	if _, exists := secondLastMap["FikoYT"]; !exists {
		// "FikoYT" anahtarı yoksa, ekleyelim
		secondLastMap["FikoYT"] = map[string]interface{}{
			"kid":          nil,
			"cihaz_kimlik": nil,
		}
	}

	// Eğer mevcut map'in içinde "FikoYT" varsa, ekleme yapmadan devam ediyoruz
	// Sonunda, array'in sonuna nil ekleyelim
	data = append(data, nil)

	return data
}

func ClientBaglandi(client *socket.Socket) {
	// log.Println("Base İo Client Connect", client.Id())

	// client.On("message", func(args ...interface{}) {
	// 	client.Emit("message-back", args...)
	// 	log.Println(args)

	// })

	// client.On("disconnect", func(clients ...interface{}) {
	// 	// log.Println("Base İo Client Disconnect", client.Id())
	// })

}
