package utils

import (
	"encoding/binary"
	"flag"
	"log"
	"net"
	"time"
)

const ntpEpochOffset = 2208988800

type packet struct {
	Settings       uint8
	Stratum        uint8
	Poll           int8
	Precision      int8
	RootDelay      uint32
	RootDispersion uint32
	ReferenceID    uint32
	RefTimeSec     uint32
	RefTimeFrac    uint32
	OrigTimeSec    uint32
	OrigTimeFrac   uint32
	RxTimeSec      uint32
	RxTimeFrac     uint32
	TxTimeSec      uint32
	TxTimeFrac     uint32
}

// day 当天凌晨0点
func ZeroHourTimeOfDay(day time.Time) time.Time {
	dayStr := day.Format("2006-01-02")
	zeroHourTime, _ := ParseTimeStringToTime("2006-01-02", dayStr)
	return *zeroHourTime
}

// day 当月一号凌晨0点
func BeginningOfMonth(day time.Time) time.Time {
	dayStr := day.Format("2006-01")
	monthTime, _ := ParseTimeStringToTime("2006-01", dayStr)
	return *monthTime
}

// 指定年月的月份的月初凌晨0点和月末23点59分59秒
func MonthBeginningToEnd(year int, month int) (time.Time, time.Time) {
	beginningOfMonth := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Local)
	beginningOfNextMonth := beginningOfMonth.AddDate(0, 1, 0)
	endOfMonth := beginningOfNextMonth.Add(time.Duration(-1))
	return beginningOfMonth, endOfMonth
}

func GetNetTime() string {
	var host string
	flag.StringVar(&host, "e", "182.92.12.11:123", "NTP host")
	flag.Parse()

	conn, err := net.Dial("udp", host)
	if err != nil {
		log.Fatalf("failed to connect: %v", err)
	}
	defer conn.Close()
	if err := conn.SetDeadline(time.Now().Add(15 * time.Second)); err != nil {
		log.Fatalf("failed to set deadline: %v", err)
	}

	req := &packet{Settings: 0x1B}

	if err := binary.Write(conn, binary.BigEndian, req); err != nil {
		log.Fatalf("failed to send request: %v", err)
	}

	rsp := &packet{}
	if err := binary.Read(conn, binary.BigEndian, rsp); err != nil {
		log.Fatalf("failed to read server response: %v", err)
	}
	secs := float64(rsp.TxTimeSec) - ntpEpochOffset
	nanos := (int64(rsp.TxTimeFrac) * 1e9) >> 32
	showtime := time.Unix(int64(secs), nanos)
	return time.Unix(showtime.Unix(), 0).Format("2006-01-02 15:04:05")
}
