package main

import (
	"context"
	"flag"
	"log"
	"log/slog"
	"net/http"
	"os"
	"os/signal"
	"syscall"

	"keikos.work/app"
	"keikos.work/assets"
)

var (
	port uint = 8080
	dev  bool = false

	webFlags   *flag.FlagSet = nil
	adminFlags *flag.FlagSet = nil

	minioAccessKeyID     = os.Getenv("AWS_ACCESS_KEY_ID")
	minioSecretAccessKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
	minioEndpoint        = os.Getenv("AWS_ENDPOINT_URL")
	minioSSL             = false
)

func init() {
	webFlags = flag.NewFlagSet("web", flag.ExitOnError)

	webFlags.UintVar(&port, "port", 8080, "The port to be used")
	webFlags.BoolVar(&dev, "dev", false, "Run the server in development mode")

	webFlags.StringVar(&minioAccessKeyID, "aws-access-key-id", os.Getenv("AWS_ACCESS_KEY_ID"), "")
	webFlags.StringVar(
		&minioSecretAccessKey,
		"aws-access-key-secret",
		os.Getenv("AWS_SECRET_ACCESS_KEY"),
		"",
	)
	webFlags.StringVar(&minioEndpoint, "aws-enpoint", os.Getenv("AWS_ENDPOINT_URL"), "")
	webFlags.BoolVar(&minioSSL, "aws-ssl", false, "")
}

func init() {
	adminFlags = flag.NewFlagSet("admin", flag.ExitOnError)

	adminFlags.UintVar(&port, "port", 8080, "The port to be used")
	adminFlags.BoolVar(&dev, "dev", false, "Run the server in development mode")

	adminFlags.StringVar(&minioAccessKeyID, "aws-access-key-id", os.Getenv("AWS_ACCESS_KEY_ID"), "")
	adminFlags.StringVar(
		&minioSecretAccessKey,
		"aws-access-key-secret",
		os.Getenv("AWS_SECRET_ACCESS_KEY"),
		"",
	)
	adminFlags.StringVar(&minioEndpoint, "aws-enpoint", os.Getenv("AWS_ENDPOINT_URL"), "")
	adminFlags.BoolVar(&minioSSL, "aws-ssl", false, "")
}

func main() {
	if len(os.Args) < 2 {
		log.Fatalf("Expected 'web' or 'admin' subcommands")
	}

	/* 	s3, err := minio.New(minioEndpoint, &minio.Options{
	   		Creds:  credentials.NewStaticV4(minioAccessKeyID, minioSecretAccessKey, ""),
	   		Secure: minioSSL,
	   	})
	   	if err != nil {
	   		panic(err)
	   	} */

	var a app.App
	var l *slog.Logger

	switch os.Args[1] {
	case "web":
		webFlags.Parse(os.Args[2:])

		var level slog.Leveler
		if dev {
			level = slog.LevelDebug
		} else {
			level = slog.LevelInfo
		}
		l = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: level}))

		var assetsHandler http.Handler
		if dev {
			assetsHandler = http.StripPrefix("/assets/", http.FileServer(http.Dir("./assets")))
		} else {
			assetsHandler = http.StripPrefix("/assets/", http.FileServerFS(assets.ASSETS))
		}

		a = app.NewWeb(app.Options{
			Port:        port,
			Development: dev,
			Log:         l,

			S3: nil,

			Assets: assetsHandler,
		})
	case "admin":
		adminFlags.Parse(os.Args[2:])

		var level slog.Leveler
		if dev {
			level = slog.LevelDebug
		} else {
			level = slog.LevelInfo
		}
		l = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: level}))

		var assetsHandler http.Handler
		if dev {
			assetsHandler = http.StripPrefix("/assets/", http.FileServer(http.Dir("./assets")))
		} else {
			assetsHandler = http.StripPrefix("/assets/", http.FileServerFS(assets.ASSETS))
		}

		a = app.NewAdmin(app.Options{
			Port:        port,
			Development: dev,
			Log:         l,

			S3: nil,

			Assets: assetsHandler,
		})
	default:
		log.Fatalf("Command %q is not available", os.Args[1])
	}

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

	if dev {
		l.Info("RUNNING IN DEVELOPMENT MODE")
	}

	go func() {
		if err := a.Start(); err != nil {
			l.Error("Failed to start server", slog.String("error", err.Error()))
		}
	}()

	<-ctx.Done()
	l.Info("Shutting down")
	if err := a.Stop(); err != nil {
		l.Error("Failed to shut down", slog.String("error", err.Error()))
	}

	l.Info("FINAL")
}
