package main

import (
	"context"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"firewall_containers/network-go/config"
	"firewall_containers/network-go/docker"
	"firewall_containers/network-go/firewall"
	"firewall_containers/network-go/iptables"
	"firewall_containers/network-go/watcher"
)

// Config path - can be overridden via environment variable
const defaultConfigPath = "/etc/user/config/networks.json"

// Watch period - can be overridden via environment variable
const defaultWatchPeriod = 30 * time.Second

func getConfigPath() string {
	path := os.Getenv("NETWORKS_CONFIG_PATH")
	if path == "" {
		return defaultConfigPath
	}
	return path
}

func getWatchPeriod() time.Duration {
	periodStr := os.Getenv("WATCH_PERIOD_SECONDS")
	if periodStr == "" {
		return defaultWatchPeriod
	}
	seconds, err := time.ParseDuration(periodStr + "s")
	if err != nil {
		log.Printf("MAIN: invalid WATCH_PERIOD_SECONDS=%s, using default %s", periodStr, defaultWatchPeriod)
		return defaultWatchPeriod
	}
	return seconds
}

func getDebug() bool {
	return os.Getenv("DEBUG") == "1" || os.Getenv("DEBUG") == "true"
}

func main() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	log.Println("MAIN: starting network-go firewall container manager")

	configPath := getConfigPath()
	watchPeriod := getWatchPeriod()
	debug := getDebug()

	log.Printf("MAIN: config path = %s", configPath)
	log.Printf("MAIN: watch period = %s", watchPeriod)
	log.Printf("MAIN: debug = %v", debug)

	// Create Docker client (uses DOCKER_HOST env var automatically)
	dockerClient, err := docker.NewClient()
	if err != nil {
		log.Fatalf("MAIN: failed to create Docker client: %v", err)
	}
	defer dockerClient.Close()

	// Create iptables manager
	iptablesMgr := iptables.NewManager(debug)

	ctx := context.Background()

	// Load initial config
	cfg, err := config.Load(configPath)
	if err != nil {
		log.Fatalf("MAIN: failed to load initial config: %v", err)
	}

	// Create the firewall orchestrator (needs config for resolver)
	orchestrator := firewall.NewOrchestrator(dockerClient, iptablesMgr, cfg)

	// Run full reconciliation
	orchestrator.ReconcileAll(ctx, cfg)

	// Set up file watcher to detect changes and re-reconcile
	onChange := func() {
		log.Println("MAIN: config file change detected, reloading and reconciling")
		newCfg, err := config.Load(configPath)
		if err != nil {
			log.Printf("MAIN: failed to reload config: %v", err)
			return
		}
		orchestrator.ReconcileAll(ctx, newCfg)
	}

	fileWatcher := watcher.NewFileWatcher(configPath, watchPeriod, onChange)
	fileWatcher.Start()

	// Wait for shutdown signal
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)

	sig := <-sigCh
	log.Printf("MAIN: received signal %v, shutting down", sig)
	fileWatcher.Stop()
	log.Println("MAIN: shutdown complete")
}