package main

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	"github.com/spf13/cobra"
	"go.uber.org/fx"

	"iop/apps/edge/internal/bootstrap"
	"iop/apps/edge/internal/edgecmd"
	"iop/packages/go/config"
)

var cfgFile string

func main() {
	if err := rootCmd().Execute(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func rootCmd() *cobra.Command {
	return edgecmd.NewRoot(edgecmd.Options{
		ConfigPath: &cfgFile,
		Serve:      serveCmd(),
		Console:    consoleCmd(),
	})
}

func serveCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "serve",
		Short: "Start the edge server",
		RunE: func(cmd *cobra.Command, _ []string) error {
			cfg, err := loadRuntimeConfig(cmd)
			if err != nil {
				return err
			}
			fx.New(bootstrap.Module(cfg)).Run()
			return nil
		},
	}
}

func consoleCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "console",
		Short: "Start the edge server with an interactive node console",
		RunE: func(cmd *cobra.Command, _ []string) error {
			cfg, err := loadRuntimeConfig(cmd)
			if err != nil {
				return err
			}
			return runConsole(context.Background(), cfg, os.Stdin, os.Stdout)
		},
	}
}

func loadRuntimeConfig(cmd *cobra.Command) (*config.EdgeConfig, error) {
	cfg, _, err := edgecmd.LoadEdgeConfig(cmd)
	if err != nil {
		return nil, err
	}
	logPath, err := edgecmd.ResolveEdgeLogPath(cfg.Logging.Path)
	if err != nil {
		return nil, err
	}
	if dir := filepath.Dir(logPath); dir != "" && dir != "." {
		if err := os.MkdirAll(dir, 0o755); err != nil {
			return nil, fmt.Errorf("mkdir log dir %s: %w", dir, err)
		}
	}
	cfg.Logging.Path = logPath
	cfg.Bootstrap.ArtifactDir = edgecmd.ResolveBootstrapArtifactDir(cfg.Bootstrap.ArtifactDir)
	return cfg, nil
}
