package netmgrd

import (
	"context"
	"net"
	"net/http"
	"os/exec"
	"strings"
	"time"
)

const (
	///////////////////////////////////////
	// 白名单联网检测地址
	TEST_URL1 = "www.aliyun.com"
	TEST_URL2 = "http://8.136.98.49"
	TEST_HOST = "223.5.5.5" // 阿里云DNS主机
	///////////////////////////////////////
	TEST_TIMEOUT = 5 * time.Second
)

func test1() bool {
	ctx, cancel := context.WithTimeout(context.Background(), TEST_TIMEOUT)
	defer cancel()

	addrs, err := net.DefaultResolver.LookupHost(ctx, TEST_URL1)
	return err == nil && len(addrs) > 0
}

func test2() bool {
	ctx, cancel := context.WithTimeout(context.Background(), TEST_TIMEOUT)
	defer cancel()

	cmd := exec.CommandContext(ctx, "ping", "-c", "3", "-W", "3", TEST_HOST)

	out, err := cmd.CombinedOutput()
	if err != nil {
		return false
	}

	return strings.Contains(strings.ToLower(string(out)), "ttl=")
}

func tcpReachable(addr string, timeout time.Duration) bool {
	conn, err := net.DialTimeout("tcp", addr, timeout)
	if err != nil {
		return false
	}
	conn.Close()
	return true
}

func test3() bool {
	return tcpReachable(TEST_HOST+":53", TEST_TIMEOUT)
}

func test4() (bool, time.Time) { // HTTP访问测试(不跟随重定向)
	client := http.Client{
		Timeout: TEST_TIMEOUT,
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}

	resp, err := client.Head(TEST_URL2)
	if err != nil {
		return false, time.Time{}
	}
	defer resp.Body.Close()

	date := resp.Header.Get("Date")
	if date == "" {
		return true, time.Time{}
	}

	t, err := time.Parse(http.TimeFormat, date)
	if err != nil {
		return true, time.Time{}
	}

	return true, t
}

func CheckNetwork() (dnsOK, pingOK, tcpOK, httpOK bool, httpTime time.Time) {
	bOK1 := test1()
	bOK3 := test3() || tcpReachable(TEST_HOST+":80", TEST_TIMEOUT) ||
		tcpReachable("8.136.98.49:80", TEST_TIMEOUT) || tcpReachable("8.136.98.49:61883", TEST_TIMEOUT)
	bOK4, httpDate := test4()
	bOK2 := bOK3 || bOK4 || test2()
	return bOK1, bOK2, bOK3, bOK4, httpDate
}
