package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"os/signal"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/pingcap-inc/nexuscrm-api-host/gateway"
)

var version = "dev"

func main() {
	if err := run(); err != nil {
		log.Printf("gateway stopped: %v", err)
		os.Exit(1)
	}
}

func run() error {
	routes, err := gateway.LoadRouteConfig(requiredEnv("GATEWAY_ROUTE_CONFIG"))
	if err != nil {
		return err
	}
	maxInFlight, err := positiveIntEnv("GATEWAY_MAX_IN_FLIGHT")
	if err != nil {
		return err
	}
	handler, err := gateway.New(gateway.Config{
		Version:     version,
		MaxInFlight: maxInFlight,
		Routes:      routes,
	})
	if err != nil {
		return err
	}
	shutdownTimeout, err := durationEnv("GATEWAY_SHUTDOWN_TIMEOUT", 0)
	if err != nil {
		return err
	}
	server, err := gateway.NewServer(handler, gateway.ServerConfig{
		ListenAddress:   requiredEnv("GATEWAY_LISTEN_ADDRESS"),
		TLSCertFile:     requiredEnv("GATEWAY_TLS_CERT_FILE"),
		TLSKeyFile:      requiredEnv("GATEWAY_TLS_KEY_FILE"),
		ShutdownTimeout: shutdownTimeout,
	})
	if err != nil {
		return err
	}
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
	defer stop()
	log.Printf("gateway starting version=%s route_revision=%s route_digest=%s", version, routes.Revision, routes.Digest)
	return server.Run(ctx)
}

func requiredEnv(name string) string {
	return strings.TrimSpace(os.Getenv(name))
}

func positiveIntEnv(name string) (int, error) {
	raw := requiredEnv(name)
	value, err := strconv.Atoi(raw)
	if err != nil || value <= 0 {
		return 0, fmt.Errorf("gateway: %s must be a positive integer", name)
	}
	return value, nil
}

func durationEnv(name string, fallback time.Duration) (time.Duration, error) {
	raw := requiredEnv(name)
	if raw == "" {
		return fallback, nil
	}
	value, err := time.ParseDuration(raw)
	if err != nil || value <= 0 {
		return 0, fmt.Errorf("gateway: %s must be a positive duration", name)
	}
	return value, nil
}
