/*
 * Copyright (c) 2025  The AdvantEDGE Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on ance "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package sssmgr

import (
	"fmt"
	"math/rand"
	"reflect"
	"testing"

	log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger"
)

const tmName = "meep-iot"
const tmNamespace = "sandboxtest"

func TestNewSssMgr(t *testing.T) {
	fmt.Println("--- ", t.Name())
	log.MeepTextLogInit(t.Name())

	// Invalid Connector
	fmt.Println("Invalid SSS Asset Manager")
	tm, err := NewSssMgr("", tmNamespace, nil, nil, nil)
	if err == nil || tm != nil {
		t.Fatalf("DB connection should have failed")
	}

	// Valid Connector
	fmt.Println("Create valid SSS Asset Manager")
	tm, err = NewSssMgr(tmName, tmNamespace, nil, nil, nil)
	if err != nil || tm == nil {
		t.Fatalf("Failed to create SSS Asset Manager")
	}

	// Cleanup
	err = tm.DeleteSssMgr()
	if err != nil {
		t.Fatalf("Failed to cleanup SSS Asset Manager")
	}
}

func TestPopulateDevicesPerIotPlatforms(t *testing.T) {
	fmt.Println("--- ", t.Name())
	log.MeepTextLogInit(t.Name())

	// Valid Connector
	fmt.Println("Create valid SSS Asset Manager")
	tm, err := NewSssMgr(tmName, tmNamespace, nil, nil, nil)
	if err != nil || tm == nil {
		t.Fatalf("Failed to create SSS Asset Manager")
	}

	err = tm.populateDevicesPerIotPlatforms()
	if err != nil {
		t.Fatalf(err.Error())
	}

	// Cleanup
	err = tm.DeleteSssMgr()
	if err != nil {
		t.Fatalf("Failed to cleanup SSS Asset Manager")
	}
}

func TestSensorDiscoveryInfoAll(t *testing.T) {
	fmt.Println("--- ", t.Name())
	log.MeepTextLogInit(t.Name())

	// Valid Connector
	fmt.Println("Create valid SSS Asset Manager")
	tm, err := NewSssMgr(tmName, tmNamespace, nil, nil, nil)
	if err != nil || tm == nil {
		t.Fatalf("Failed to create SSS Asset Manager")
	}

	err = tm.populateDevicesPerIotPlatforms()
	if err != nil {
		t.Fatalf(err.Error())
	}

	sensors, err := tm.SensorDiscoveryInfoAll()
	if err != nil {
		t.Fatalf(err.Error())
	}
	fmt.Println("sensors: ", sensors)

	// Cleanup
	err = tm.DeleteSssMgr()
	if err != nil {
		t.Fatalf("Failed to cleanup SSS Asset Manager")
	}
}

func TestGetSensor(t *testing.T) {
	fmt.Println("--- ", t.Name())
	log.MeepTextLogInit(t.Name())

	// Valid Connector
	fmt.Println("Create valid SSS Asset Manager")
	tm, err := NewSssMgr(tmName, tmNamespace, nil, nil, nil)
	if err != nil || tm == nil {
		t.Fatalf("Failed to create SSS Asset Manager")
	}

	err = tm.populateDevicesPerIotPlatforms()
	if err != nil {
		t.Fatalf(err.Error())
	}

	sensors, err := tm.SensorDiscoveryInfoAll()
	if err != nil {
		t.Fatalf(err.Error())
	}
	fmt.Println("sensors: ", sensors)

	idx := rand.Int31n(int32(len(sensors)))
	sensor, err := tm.GetSensor(sensors[idx].SensorIdentifier)
	if err != nil {
		t.Fatalf(err.Error())
	}
	fmt.Println("sensor: ", sensor)
	if !validate_sensor_discovery_info(sensors[idx], sensor) {
		t.Fatalf("Value mismatch")
	}

	// Cleanup
	err = tm.DeleteSssMgr()
	if err != nil {
		t.Fatalf("Failed to cleanup SSS Asset Manager")
	}
}

// func TestOneM2mCreateAEAndCNT(t *testing.T) {
// 	fmt.Println("--- ", t.Name())
// 	log.MeepTextLogInit(t.Name())

// 	// Valid Connector
// 	fmt.Println("Create valid SSS Asset Manager")
// 	tm, err := NewSssMgr(tmName, tmNamespace, nil, nil, nil)
// 	if err != nil || tm == nil {
// 		t.Fatalf("Failed to create SSS Asset Manager")
// 	}

// 	// Register new IotPlatform and create AE entry
// 	fmt.Println("Register new IotPlatform and create AE entry")
// 	iotPlatformInfo, err := registerIotPltfAndCreateAE(tm)
// 	if err != nil {
// 		t.Fatalf("registerIotPltfAndCreateAE failure")
// 	}
// 	// Get the new IotPlatform and create AE entry
// 	fmt.Println("Get the new IotPlatform and create AE entry")
// 	deviceResp_1, err := tm.oneM2M_get(*iotPlatformInfo.DeviceInfo, iotPlatformInfo.IotPlatformId, "AE")
// 	if err != nil {
// 		t.Fatalf("oneM2M_get failure")
// 	}
// 	// Check deviceResp vs. deviceResp_1
// 	fmt.Println("Check deviceResp vs. deviceResp_1")
// 	if !validate_device_info(*iotPlatformInfo.DeviceInfo, deviceResp_1) {
// 		t.Fatalf("validate_device_info failure")
// 	}

// 	// Create a device for the IotPlatform
// 	var device = DeviceInfo{
// 		RequestedIotPlatformId: iotPlatformInfo.IotPlatformId,
// 		SensorIdentifier:               "Device1",
// 		Enabled:                true,
// 		//DeviceMetadata:         [KeyValuePair{Key: "pi", Value: *iotPlatformInfo.DeviceInfo.DeviceMetadata[]}]
// 	}
// 	device, err = tm.oneM2M_create(device, iotPlatformInfo.IotPlatformId, "CNT")
// 	if err != nil {
// 		t.Fatalf("oneM2M_create failed to create a device")
// 	}
// 	fmt.Println("device: ", device)

// 	// Delete the new IotPlatform entry
// 	fmt.Println("Delete the new IotPlatform entry")
// 	err = tm.oneM2M_delete(*iotPlatformInfo.DeviceInfo, iotPlatformInfo.IotPlatformId, "AE")
// 	if err != nil {
// 		t.Fatalf("oneM2M_create failure")
// 	}

// 	// Cleanup
// 	err = tm.DeleteSssMgr()
// 	if err != nil {
// 		t.Fatalf("Failed to cleanup SSS Asset Manager")
// 	}

// 	// t.Fatalf("DONE")
// }

// func registerIotPltfAndCreateAE(tm *SssMgr) (iotPlatformInfo IotPlatformInfo, err error) {

// 	// Set a valid platform
// 	var adresses = []Addresses{}
// 	adresses = append(adresses, Addresses{
// 		Host: "172.29.10.56",
// 		Port: 1883,
// 	})
// 	var endpoint = EndPointInfo{
// 		Addresses: adresses,
// 	}
// 	var userTransportInfo = []MbTransportInfo{}
// 	userTransportInfo = append(userTransportInfo, MbTransportInfo{
// 		Id:          "d5673793-c55c-4969-b5bc-2121f84b9f8d",
// 		Name:        "MQTT",
// 		Description: "MQTT",
// 		Protocol:    "MQTT",
// 		Version:     "2",
// 		Endpoint:    &endpoint,
// 	})
// 	var adresses_1 = []Addresses{}
// 	adresses_1 = append(adresses_1, Addresses{
// 		Host: "172.29.10.20",
// 		Port: 31110,
// 	})
// 	var customServicesTransportInfo = []TransportInfo{}
// 	var endPointInfo_1 = EndPointInfo{
// 		Addresses: adresses_1,
// 	}
// 	customServicesTransportInfo = append(customServicesTransportInfo, TransportInfo{
// 		Id:          "2ddb713c-2b41-4ded-a7ad-a5a047c5df13",
// 		Name:        "/laboai-acme-ic-cse",
// 		Description: "ACME oneM2M CSE",
// 		Protocol:    "REST_HTTP",
// 		Version:     "4",
// 		Endpoint:    &endPointInfo_1,
// 	})
// 	iotPlatformInfo = IotPlatformInfo{
// 		IotPlatformId:               "523f2df1-8927-429f-906c-56ba92d13762",
// 		UserTransportInfo:           userTransportInfo,
// 		CustomServicesTransportInfo: customServicesTransportInfo,
// 		Enabled:                     true,
// 	}
// 	err = tm.RegisterIotPlatformInfo(iotPlatformInfo)
// 	if err != nil {
// 		return iotPlatformInfo, err
// 	}

// 	// OneM2M create MEC pltf as an AE
// 	requestedIotPlatformId := iotPlatformInfo.IotPlatformId
// 	var device = DeviceInfo{
// 		RequestedIotPlatformId: requestedIotPlatformId,
// 		SensorIdentifier:               requestedIotPlatformId,
// 		Enabled:                true,
// 	}
// 	d, err := tm.oneM2M_create(device, requestedIotPlatformId, "AE")
// 	if err != nil {
// 		return iotPlatformInfo, err
// 	}
// 	iotPlatformInfo.DeviceInfo = new(DeviceInfo)
// 	*iotPlatformInfo.DeviceInfo = d
// 	fmt.Println("iotPlatformInfo.DeviceInfo: ", *iotPlatformInfo.DeviceInfo)

// 	return iotPlatformInfo, nil
// }

func validate_sensor_discovery_info(expected_sensor SensorDiscoveryInfo, received_sensor SensorDiscoveryInfo) bool {
	fmt.Println(">>> validate_sensor_discovery_info: expected_sensor: ", expected_sensor)
	fmt.Println(">>> validate_sensor_discovery_info: received_sensor: ", received_sensor)

	if expected_sensor.SensorIdentifier != received_sensor.SensorIdentifier {
		fmt.Println("received_sensor.SensorIdentifier != SensorIdentifier")
		return false
	}
	if len(expected_sensor.SensorPropertyList) != len(received_sensor.SensorPropertyList) {
		fmt.Println("len(received_sensor.SensorPropertyList) != len(SensorPropertyList)")
		return false
	} else if !reflect.DeepEqual(expected_sensor.SensorPropertyList, received_sensor.SensorPropertyList) {
		fmt.Println("received_sensor.SensorPropertyList != SensorPropertyList")
	}
	if len(expected_sensor.SensorCharacteristicList) != len(received_sensor.SensorCharacteristicList) {
		fmt.Println("len(received_sensor.SensorCharacteristicList) != len(SensorCharacteristicList)")
		return false
	} else if !reflect.DeepEqual(expected_sensor.SensorCharacteristicList, received_sensor.SensorCharacteristicList) {
		fmt.Println("received_sensor.SensorCharacteristicList != SensorCharacteristicList")
	}
	// TODO To be continued

	return true
}
