package main

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"strings"

	"be.ems/features/dbrest"
	"be.ems/features/event"
	"be.ems/features/fm"
	"be.ems/features/lm"
	"be.ems/features/pm"
	"be.ems/lib/dborm"
	"be.ems/lib/global"
	"be.ems/lib/log"
	"be.ems/lib/routes"
	"be.ems/restagent/config"
	"be.ems/src"
	"be.ems/src/framework/middleware"
	libSession "be.ems/src/lib_features/session"
	"github.com/gin-gonic/gin"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/h2c"
)

// const defaultConfigFile = "./etc/restconf.yaml"

// func init() {
// 	cfile := flag.String("c", defaultConfigFile, "config file")
// 	pv := flag.Bool("v", false, "print version")
// 	ph := flag.Bool("h", false, "print help")

// 	flag.Parse()
// 	if *pv {
// 		fmt.Printf("OMC restagent version: %s\n%s\n%s\n\n", global.Version, global.BuildTime, global.GoVer)
// 		os.Exit(0)
// 	}
// 	if *ph {
// 		flag.Usage()
// 		os.Exit(0)
// 	}

// 	config.ReadConfig(*cfile)
// 	config.UriPrefix = config.GetYamlConfig().OMC.UriPrefix
// 	//fmt.Println(config.UriPrefix)
// }

// func listenIPv6(ipv6 string, port int) {
// 	//
// 	addr := &net.TCPAddr{
// 		IP:   net.ParseIP(ipv6),
// 		Port: port,
// 	}

// 	listener, err := net.ListenTCP("tcp6", addr)
// 	if err != nil {
// 		fmt.Println("Failed to listen:", err)
// 		return
// 	}

// 	server := &http.Server{}
// 	err = server.Serve(listener)
// 	if err != nil {
// 		fmt.Println("Failed to serve:", err)
// 	}
// }

func HttpListen(addr string, router http.Handler) {
	// 创建HTTP服务器
	h2s := &http2.Server{
		// ...
	}
	server := &http.Server{
		Addr:    addr,
		Handler: h2c.NewHandler(router, h2s),
	}

	// // support http 2.0 server
	// err := http2.ConfigureServer(server, &http2.Server{})
	// if err != nil {
	// 	fmt.Println("ConfigureServer err:", err)
	// 	os.Exit(11)
	// }
	err := server.ListenAndServe()
	if err != nil {
		fmt.Println("ListenAndServe err:", err)
		os.Exit(12)
	}
}

func HttpListenTLS(addr, caFile, certFile, keyFile string, clientAuthType int, router http.Handler) {
	// 加载根证书
	caCert, err := os.ReadFile(caFile)
	if err != nil {
		log.Fatal(err)
	}
	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)

	// 创建自定义的TLS配置
	tlsConfig := &tls.Config{
		MinVersion: tls.VersionTLS10,
		MaxVersion: tls.VersionTLS13,
		ClientCAs:  caCertPool,
		ClientAuth: tls.ClientAuthType(clientAuthType),
	}

	// 创建HTTP服务器
	server := &http.Server{
		Addr:      addr,
		Handler:   router,
		TLSConfig: tlsConfig,
	}

	// support http 2.0 server
	http2.ConfigureServer(server, &http2.Server{})
	if err != nil {
		fmt.Println("ConfigureServer err:", err)
		os.Exit(13)
	}
	err = server.ListenAndServeTLS(certFile, keyFile)
	if err != nil {
		fmt.Println("ListenAndServeTLS err:", err)
		os.Exit(14)
	}
}

func HttpListenWebServerTLS(addr, caFile, certFile, keyFile string, clientAuthType int) {
	// 加载根证书
	caCert, err := os.ReadFile(caFile)
	if err != nil {
		log.Fatal(err)
	}
	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)

	// 创建自定义的TLS配置
	tlsConfig := &tls.Config{
		MinVersion: tls.VersionTLS10,
		MaxVersion: tls.VersionTLS13,
		ClientCAs:  caCertPool,
		ClientAuth: tls.ClientAuthType(clientAuthType),
	}

	// 创建HTTP服务器
	server := &http.Server{
		Addr:      addr,
		TLSConfig: tlsConfig,
	}

	// support http 2.0 server
	http2.ConfigureServer(server, &http2.Server{})
	if err != nil {
		fmt.Println("ConfigureServer err:", err)
		os.Exit(9)
	}
	err = server.ListenAndServeTLS(certFile, keyFile)
	if err != nil {
		fmt.Println("ListenAndServeTLS err:", err)
		os.Exit(10)
	}
}

func HttpListenWebServer(addr string) {
	// 创建HTTP服务器
	server := &http.Server{
		Addr: addr,
	}

	// support http 2.0 server
	err := http2.ConfigureServer(server, &http2.Server{})
	if err != nil {
		fmt.Println("ConfigureServer err:", err)
		os.Exit(7)
	}
	err = server.ListenAndServe()
	if err != nil {
		fmt.Println("ListenAndServe err:", err)
		os.Exit(8)
	}
}

func main() {
	// src 配置中心初始加载
	src.ConfigurationInit()
	app := src.AppEngine()

	conf := config.GetYamlConfig()

	log.InitLogger(conf.Logger.File, conf.Logger.Duration, conf.Logger.Count, "omc:restagent", config.GetLogLevel())
	fmt.Printf("OMC restagent version: %s\n", global.Version)
	log.Infof("========================= OMC restagent startup =========================")
	log.Infof("OMC restagent version: %s %s %s", global.Version, global.BuildTime, global.GoVer)

	err := dborm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
		conf.Database.Host, conf.Database.Port, conf.Database.Name)
	if err != nil {
		fmt.Println("dborm.initDbClient err:", err)
		os.Exit(4)
	}
	err = fm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
		conf.Database.Host, conf.Database.Port, conf.Database.Name)
	if err != nil {
		fmt.Println("dborm.initDbClient err:", err)
		os.Exit(4)
	}
	err = pm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
		conf.Database.Host, conf.Database.Port, conf.Database.Name)
	if err != nil {
		fmt.Println("dborm.initDbClient err:", err)
		os.Exit(4)
	}
	err = dbrest.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
		conf.Database.Host, conf.Database.Port, conf.Database.Name)
	if err != nil {
		fmt.Println("dbrest.initDbClient err:", err)
		os.Exit(4)
	}
	err = lm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
		conf.Database.Host, conf.Database.Port, conf.Database.Name)
	if err != nil {
		fmt.Println("lm.initDbClient err:", err)
		os.Exit(4)
	}

	// 将 mux.Router 注册到 gin.Engine

	// 默认路由组
	defaultUriGroup := app.Group(config.DefaultUriPrefix)
	defaultUriGroup.Use(middleware.PreAuthorize(nil))
	defaultUriGroup.Use(libSession.SessionHeader())
	defaultUriGroup.Any("/*any", gin.WrapH(routes.NewRouter()))
	// 可配置前缀路由组
	uriGroup := app.Group(config.UriPrefix)
	uriGroup.Use(libSession.SessionHeader())
	uriGroup.Any("/*any", gin.WrapH(routes.NewRouter()))
	// AMF上报的UE事件, 无前缀，暂时特殊处理
	app.POST(event.UriUEEvent, event.PostUEEventFromAMF)

	// 开启监控采集
	// monitor.StartMonitor(false, "")

	for _, rest := range conf.Rest {
		// ipv4 goroutines
		if rest.IPv4 != "" {
			listen := rest.IPv4 + ":" + strconv.Itoa(int(rest.Port))
			if strings.ToLower(rest.Scheme) == "https" {
				go HttpListenTLS(listen, rest.CaFile, rest.CertFile, rest.KeyFile, rest.ClientAuthType, app)
			} else {
				go HttpListen(listen, app)
			}
		}
		if rest.IPv4 != "0.0.0.0" {
			// 默认启动localhost侦听
			listenLocal := "127.0.0.1" + ":" + strconv.Itoa(int(rest.Port))
			if strings.ToLower(rest.Scheme) == "https" {
				go HttpListenTLS(listenLocal, rest.CaFile, rest.CertFile, rest.KeyFile, rest.ClientAuthType, app)
			} else {
				go HttpListen(listenLocal, app)
			}
		}
		// ipv6 goroutines
		if rest.IPv6 != "" {
			listenv6 := "[" + rest.IPv6 + "]" + ":" + strconv.Itoa(int(rest.Port))
			if strings.ToLower(rest.Scheme) == "https" {
				go HttpListenTLS(listenv6, rest.CaFile, rest.CertFile, rest.KeyFile, rest.ClientAuthType, app)
			} else {
				go HttpListen(listenv6, app)
			}
		}

		// if rest.IPv6 != "::" {
		// 	// 默认启动localhost侦听
		// 	listenv6Local := "[" + "::1" + "]" + ":" + strconv.Itoa(int(rest.Port))
		// 	if strings.ToLower(rest.Scheme) == "https" {
		// 		go HttpListenTLS(listenv6Local, rest.CaFile, rest.CertFile, rest.KeyFile, app)
		// 	} else {
		// 		go HttpListen(listenv6Local, app)
		// 	}
		// }
	}

	if conf.WebServer.Enabled {
		fs := http.FileServer(http.Dir(conf.WebServer.RootDir))
		http.Handle("/", fs)
		for _, listen := range conf.WebServer.Listen {
			if strings.ToLower(listen.Scheme) == "https" {
				go HttpListenWebServerTLS(listen.Addr, listen.CaFile, listen.CertFile, listen.KeyFile, listen.ClientAuthType)
			} else {
				go HttpListenWebServer(listen.Addr)
			}
		}
	}

	select {}
}
