package main

import (
	"context"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	"github.com/tidbcloud/AgentTeam/envcompat"
	"github.com/tidbcloud/AgentTeam/internal/config"
	"github.com/tidbcloud/AgentTeam/internal/observability/logging"
	"github.com/tidbcloud/AgentTeam/internal/server"
	"github.com/tidbcloud/AgentTeam/internal/versioning"
)

func main() {
	os.Exit(run(os.Args[1:], os.Stdout, os.Stderr))
}

func run(args []string, output io.Writer, bootstrap io.Writer) (exitCode int) {
	if handleVersion(args, output) {
		return 0
	}

	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
	defer stop()

	cfg, err := config.LoadFromEnv()
	if err != nil {
		logging.WriteBootstrapError(bootstrap, "load config", err)
		return 1
	}

	pipeline, err := logging.Open(cfg.Log, output)
	if err != nil {
		logging.WriteBootstrapError(bootstrap, "initialize logging", err)
		return 1
	}
	logger := pipeline.Logger()
	previousLogger := slog.Default()
	slog.SetDefault(logger)
	defer slog.SetDefault(previousLogger)
	defer func() {
		if err := pipeline.Close(); err != nil {
			logging.WriteBootstrapError(bootstrap, "close logging", err)
			exitCode = 1
		}
	}()
	defer logging.RecoverPanic(logger)
	envcompat.WarnLegacyOnce(logger)
	srv, err := server.New(ctx, cfg, logger)
	if err != nil {
		logger.Error("create server", slog.Any("error", err))
		return 1
	}
	defer srv.Close()

	if err := srv.Run(ctx); err != nil && !errors.Is(err, http.ErrServerClosed) {
		logger.Error("run server", slog.Any("error", err))
		return 1
	}

	return 0
}

func handleVersion(args []string, output io.Writer) bool {
	for _, arg := range args {
		switch arg {
		case "--version", "-v":
			_, _ = fmt.Fprintf(output, "agentteam-server %s\n", versioning.ServerVersion())
			_, _ = fmt.Fprintf(output, "commit: %s\n", versioning.ServerGitCommit())
			if buildTime := versioning.ServerBuildTime(); buildTime != "" {
				_, _ = fmt.Fprintf(output, "built: %s\n", buildTime)
			}
			return true
		}
	}

	return false
}
