package main

import (
	"flag"
	"fmt"
	"os"
)

type FirewallRule struct {
	Type     string `yaml:"type"`
	Action   string `yaml:"action"`
	Protocol string `yaml:"protocol"`
	Dport    string `yaml:"dport"`
	Sport    string `yaml:"sport"`
	Source   string `yaml:"source"`
	Dest     string `yaml:"dest"`
	Comment  string `yaml:"comment"`
}

type WindowsConfig struct {
	ImagePath     string         `yaml:"image_path"`
	VMName        string         `yaml:"vm_name"`
	VMID          int            `yaml:"vm_id"`
	Storage       string         `yaml:"storage"`
	Memory        int            `yaml:"memory"`
	Cores         int            `yaml:"cores"`
	Sockets       int            `yaml:"sockets"`
	Bridge        string         `yaml:"bridge"`
	VlanTag       int            `yaml:"vlan_tag"`
	ProxmoxHost   string         `yaml:"proxmox_host"`
	ProxmoxUser   string         `yaml:"proxmox_user"`
	ProxmoxPass   string         `yaml:"proxmox_pass"`
	GuestAgent    bool           `yaml:"guest_agent"`
	Firewall      bool           `yaml:"firewall"`
	FirewallRules []FirewallRule `yaml:"firewall_rules"`
}

func main() {
	config := &WindowsConfig{}
	var configFile string
	var batchFile string
	var listStorage bool

	flag.StringVar(&configFile, "config", "", "Config file path (YAML)")
	flag.StringVar(&batchFile, "batch", "", "Batch file with multiple config paths (one per line)")
	flag.BoolVar(&listStorage, "list-storage", false, "List available storage on Proxmox host")
	flag.BoolVar(&listStorage, "ls", false, "List available storage on Proxmox host (shorthand)")
	flag.StringVar(&config.ImagePath, "image-path", "", "Windows cloud image path (local qcow2 file)")
	flag.StringVar(&config.VMName, "vm-name", "windows-vm", "VM name")
	flag.IntVar(&config.VMID, "vm-id", 0, "VM ID (0 = auto-find from 10000+)")
	flag.StringVar(&config.Storage, "storage", "", "Proxmox storage name")
	flag.IntVar(&config.Memory, "memory", 4096, "Memory in MB")
	flag.IntVar(&config.Cores, "cores", 2, "CPU cores")
	flag.IntVar(&config.Sockets, "sockets", 1, "CPU sockets")
	flag.StringVar(&config.Bridge, "bridge", "vmbr0", "Network bridge")
	flag.IntVar(&config.VlanTag, "vlan-tag", 0, "VLAN tag (optional, 0 = no VLAN)")
	flag.StringVar(&config.ProxmoxHost, "proxmox-host", "", "Proxmox host (e.g., 192.168.1.100)")
	flag.StringVar(&config.ProxmoxUser, "proxmox-user", "root@pam", "Proxmox user")
	flag.StringVar(&config.ProxmoxPass, "proxmox-pass", "", "Proxmox password")
	flag.BoolVar(&config.GuestAgent, "guest-agent", true, "Enable QEMU guest agent")
	flag.BoolVar(&config.Firewall, "firewall", false, "Enable firewall")

	flag.Parse()

	if listStorage || flag.Lookup("ls").Value.(flag.Getter).Get().(bool) {
		if config.ProxmoxHost == "" {
			fmt.Println("Error: -proxmox-host is required for storage listing")
			os.Exit(1)
		}
		if err := listAvailableStorage(config); err != nil {
			fmt.Printf("Error listing storage: %v\n", err)
			os.Exit(1)
		}
		return
	}

	if batchFile != "" {
		if err := processBatchFile(batchFile); err != nil {
			fmt.Printf("Error processing batch file: %v\n", err)
			os.Exit(1)
		}
		return
	}

	if configFile != "" {
		if err := loadConfig(configFile, config); err != nil {
			fmt.Printf("Error loading config: %v\n", err)
			os.Exit(1)
		}
	}

	if config.ImagePath == "" {
		fmt.Println("Error: -image-path or config file is required")
		flag.Usage()
		os.Exit(1)
	}

	if config.ProxmoxHost == "" {
		fmt.Println("Error: -proxmox-host is required")
		flag.Usage()
		os.Exit(1)
	}

	if config.Storage == "" {
		fmt.Println("Error: -storage is required")
		flag.Usage()
		os.Exit(1)
	}

	if config.VMID == 0 {
		fmt.Println("Auto-finding available VM ID starting from 10000...")
		vmid, err := findAvailableVMID(config)
		if err != nil {
			fmt.Printf("Error finding available VM ID: %v\n", err)
			os.Exit(1)
		}
		config.VMID = vmid
		fmt.Printf("Found available VM ID: %d\n", config.VMID)
	}

	fmt.Printf("Creating template %s (ID: %d) on Proxmox host %s\n", config.VMName, config.VMID, config.ProxmoxHost)

	if err := createProxmoxWindowsVM(config); err != nil {
		fmt.Printf("Error: %v\n", err)
		os.Exit(1)
	}
}
