package netmgr

import (
	"fmt"
	"os/exec"
	"sync"
	"time"

	"github.com/beevik/ntp"
)

var servers = []string{
	"210.72.145.44",
	"ntp.aliyun.com",
	"ntp.ntsc.ac.cn",
}

type ntpResult struct {
	t       time.Time
	stratum uint8
	err     error
}

func SyncNTPTime() error {
	t, err := getAccurateTime(servers, 5*time.Second)
	if err != nil {
		return err
	}
	if err := setSystemTime(t); err != nil {
		return err
	}
	return nil
}

func getAccurateTime(servers []string, timeout time.Duration) (time.Time, error) {
	ch := make(chan ntpResult, len(servers))
	var wg sync.WaitGroup
	wg.Add(len(servers))

	for _, s := range servers {
		go func(s string) {
			defer wg.Done()
			resp, err := ntp.QueryWithOptions(s, ntp.QueryOptions{Timeout: timeout})
			if err != nil || resp.Stratum == 0 || resp.Stratum > 5 || resp.Time.IsZero() {
				ch <- ntpResult{err: err} // "resp.Stratum"为0(无效服务器)或大于5(精度较低)
				return
			}
			ch <- ntpResult{t: resp.Time, stratum: resp.Stratum}
		}(s)
	}

	go func() {
		wg.Wait()
		close(ch)
	}()

	var results []ntpResult
	for r := range ch {
		if r.err == nil {
			results = append(results, r)
		}
	}

	if len(results) == 0 {
		return time.Time{}, fmt.Errorf("所有NTP服务器请求失败或无有效时间")
	}

	// 找最低 Stratum
	minStratum := uint8(255)
	for _, r := range results {
		if r.stratum < minStratum {
			minStratum = r.stratum
		}
	}

	// 最低 Stratum 的时间
	var bestTimes []time.Time
	for _, r := range results {
		if r.stratum == minStratum {
			bestTimes = append(bestTimes, r.t)
		}
	}

	return bestTimes[0], nil
}

func setSystemTime(t time.Time) error {
	cmd := exec.Command("date", "-s", t.Local().Format("2006-01-02 15:04:05"))
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%v, output: %s", err, string(output))
	}
	return nil
}
