package netmgr

import "C"

import (
	"sync/atomic"
	"time"

	modem "hnyfkj.com.cn/rtu/bxs-sy/air720u"
	"hnyfkj.com.cn/rtu/bxs-sy/baseapp"
	mqtt "hnyfkj.com.cn/rtu/bxs-sy/reporter"
)

const MODULE_NAME = "NetworkManager"

var (
	isOnline        atomic.Bool  // 标记是否联网
	offlineStartTs  atomic.Int64 // 离线开始时间
	isSyncNTPTimeOK atomic.Bool  // 标记本地时间是否已同步成功
)

const (
	interval1 = time.Duration(1) * time.Second
	interval2 = time.Duration(5) * time.Second
)

func ModuleInit() {
	go serviceRun()
}

// 联网保持服务
func serviceRun() {
	t := time.NewTimer(interval1)
	defer t.Stop()

	for {
		select {
		case <-t.C:
			// 1, 联网检测-看结果
			dnsOK, pingOK, tcpOK, httpOK := CheckNetwork()
			mqttOK := false
			if mqtt.Reporter != nil {
				mqttOK = mqtt.Reporter.IsLogin()
			}
			baseapp.Logger.Infof("[%s] 联网检测: DNS OK=%v, PING OK=%v, TCP OK=%v, HTTP OK=%v, MQTT OK=%v", MODULE_NAME, dnsOK, pingOK, tcpOK, httpOK, mqttOK)

			// 2, 检测成功-在线时
			if dnsOK && pingOK && tcpOK {
				isOnline.Store(true)
				offlineStartTs.Store(0)

				if isSyncNTPTimeOK.Load() {
					t.Reset(interval2)
					continue
				}

				err := SyncNTPTime()
				if err == nil {
					isSyncNTPTimeOK.Store(true)
					baseapp.Logger.Infof("[%s] NTP时间已同步", MODULE_NAME)
					t.Reset(interval2)
					continue
				} else {
					baseapp.Logger.Errorf("[%s] 同步NTP时间时有错误发生: %v!!", MODULE_NAME, err)
					t.Reset(interval1)
					continue
				}
			}

			// 3, 检测失败-离线时
			if isOnline.Load() { // 状态由"1"变为"0"
				isOnline.Store(false)
				offlineStartTs.Store(time.Now().UnixNano()) // 记录离线开始时间
			}

			if OfflineDuration() >= (time.Duration(60)*time.Second) && !mqttOK {
				baseapp.Logger.Warnf("[%s] 检测到网络长时间断开, 将重置4G模块!", MODULE_NAME)
				reset4gNetwork()
				offlineStartTs.Store(time.Now().UnixNano()) // 重置离线开始时间
			}

			t.Reset(interval1)
		case <-baseapp.IsExit2():
			return
		} // select end
	} // for end
}

// 返回联网状态
func IsInetAvailable() bool {
	return isOnline.Load()
}

// 时间是否同步
func IsSyncedNtpTime() bool {
	return isSyncNTPTimeOK.Load()
}

// 等待所有成功
func WaitAllOK(timeout time.Duration) bool {
	deadline := time.Now().Add(timeout)
	tick := 50 * time.Millisecond

	for {
		if IsInetAvailable() && IsSyncedNtpTime() {
			return true
		}

		remaining := time.Until(deadline)
		if remaining <= 0 {
			return false
		}

		sleep := min(tick, remaining)
		time.Sleep(sleep)
	}
}

// 返回断网时长
func OfflineDuration() time.Duration {
	if IsInetAvailable() {
		return 0
	}
	ts := offlineStartTs.Load()
	if ts == 0 {
		return 0
	}
	return time.Since(time.Unix(0, ts))
}

// 重启模块联网
func reset4gNetwork() {
	modem.ModuleExit()
	modem.ModuleInit(true)
}

//export RTU_IsInetAvailable
func RTU_IsInetAvailable() C.int {
	if IsInetAvailable() {
		return 1
	}
	return 0
}

//export RTU_IsSyncedNtpTime
func RTU_IsSyncedNtpTime() C.int {
	if IsSyncedNtpTime() {
		return 1
	}
	return 0
}
