package main

import (
	"encoding/json"
	"fmt"
	"nodemaster/models"
	"os"
	"strings"

	_ "nodemaster/routers"

	beego "github.com/beego/beego/v2/server/web"
)

func main() {
	if len(os.Args) > 1 {
		switch os.Args[1] {
		case "scan":
			runScanCLI(os.Args[2:])
			return
		case "info":
			runInfoCLI()
			return
		}
	}
	if beego.BConfig.RunMode == "dev" {
		beego.BConfig.WebConfig.DirectoryIndex = true
		beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
	}
	models.StartScheduler()
	beego.Run()
}

func runInfoCLI() {
	n := models.GetLocalNode()
	svcs := models.GetAllServices()
	nodes := models.GetAllRemoteNodes()
	fmt.Println("NodeMaster info")
	fmt.Println(strings.Repeat("─", 60))
	fmt.Printf("Config file : %s\n", models.ConfigPath())
	fmt.Printf("Hostname    : %s\n", n.Hostname)
	if n.Description != "" {
		fmt.Printf("Description : %s\n", n.Description)
	}
	fmt.Printf("Services    : %d registered\n", len(svcs))
	fmt.Printf("Remote nodes: %d registered\n", len(nodes))
	fmt.Printf("Updates     : %d records\n", len(n.UpdateHistory))
}

func runScanCLI(args []string) {
	var folder string
	jsonOutput := false
	for _, a := range args {
		switch {
		case a == "--json":
			jsonOutput = true
		case !strings.HasPrefix(a, "-"):
			folder = a
		}
	}

	result := models.ScanAll(folder)

	if jsonOutput {
		out, _ := json.MarshalIndent(result, "", "  ")
		fmt.Println(string(out))
		if len(result.Errors) > 0 {
			os.Exit(1)
		}
		return
	}

	fmt.Println("NodeMaster scan")
	fmt.Println(strings.Repeat("─", 60))
	fmt.Printf("Config file : %s\n\n", models.ConfigPath())

	if len(result.ScannedPaths) == 0 {
		fmt.Println("No scan paths found (no /opt/compose, no ~/compose dirs)")
	} else {
		fmt.Println("Paths scanned:")
		for _, p := range result.ScannedPaths {
			fmt.Printf("  %s\n", p)
		}
	}

	fmt.Printf("\nCompose files found: %d\n", result.Found)

	if len(result.Created) > 0 {
		fmt.Printf("\nCreated (%d):\n", len(result.Created))
		for _, s := range result.Created {
			printScanEntry(s)
		}
	}

	if len(result.Updated) > 0 {
		fmt.Printf("\nUpdated (%d):\n", len(result.Updated))
		for _, s := range result.Updated {
			printScanEntry(s)
		}
	}

	if len(result.Created) == 0 && len(result.Updated) == 0 {
		fmt.Println("\nNo changes (all services already up to date)")
	}

	if len(result.Errors) > 0 {
		fmt.Printf("\nErrors:\n")
		for _, e := range result.Errors {
			fmt.Fprintf(os.Stderr, "  ! %s\n", e)
		}
		os.Exit(1)
	}
}

func printScanEntry(s models.ServiceScanInfo) {
	status := s.Status
	if status == "" {
		status = "unknown"
	}
	backup := s.BackupFolder
	if backup == "" {
		backup = "(none deduced)"
	}
	fmt.Printf("  %-24s [%-7s]  backup: %s\n", s.Name, status, backup)
}
