module main

import os
import flag
import json
import time

// MVGAL CLI - Multi-Vendor GPU Aggregation Layer Control Tool
// SPDX-License-Identifier: MIT

const version = "0.2.7"
const default_socket = "/run/mvgal/mvgal.sock"

struct Config {
mut:
	socket_path string = default_socket
verbose       bool
	force       bool
}

// GPU information structure
struct GpuInfo {
	index         u32
	name          string
	vendor        string
	vram_mb       u64
	util_pct      u32
	temp_c        u32
	power_w       u32
	enabled       bool
}

// MVGAL response structure
struct MvgalResponse {
	gpus       []GpuInfo
	strategy   string
	stats      map[string]int
	daemon_running bool
}

fn print_usage() {
	eprintln("MVGAL Control Tool v${version}")
	eprintln("")
	eprintln("Usage: mvgal-ctl <command> [options]")
	eprintln("")
	eprintln("Commands:")
	eprintln("  status                  Show all GPU status")
	eprintln("  list-gpus               List all detected GPUs")
	eprintln("  create-group <gpus...>  Create aggregation group")
	eprintln("  delete-group <id>       Delete aggregation group")
	eprintln("  set-mode <id> <mode>    Set rendering mode (afr/sfr/compute)")
	eprintln("  set-power <id> <profile> Set power profile")
	eprintln("  set-curve <id> <file>   Load power curve from file")
	eprintln("  get-curve <id>          Display current power curve")
	eprintln("  set-clock <id> <min> <max> Set clock limits (MHz)")
	eprintln("  monitor                 Live monitoring mode (ncurses)")
	eprintln("  logs                    Tail daemon logs")
	eprintln("  dkms-install            Install kernel modules via DKMS")
	eprintln("  dkms-remove             Remove kernel modules via DKMS")
	eprintln("  -h, --help              Show this help")
	eprintln("  -v, --version           Show version")
	eprintln("")
	eprintln("Options:")
	eprintln("  --socket <path>         Socket path (default: ${default_socket})")
	eprintln("  --verbose               Enable verbose output")
}

fn get_version() {
	println("mvgal-ctl v${version}")
}

// Connect to daemon socket
fn connect_socket(socket_path string) ?os.File {
	mut conn := os.file_open(socket_path, 'r') or {
		return error("Failed to connect to socket: $socket_path")
	}
	return conn
}

// Send command and receive response
fn send_command(mut conn os.File, cmd string) ?string {
	// Write command
	conn.write_string(cmd)?
	conn.flush()?

	// Read response
	mut response := ""
	for {
		line := conn.read_line()?
		response += line
		if line == "\n" || line == "" {
			break
		}
	}
	return response
}

fn cmd_status(config Config) {
	println("MVGAL GPU Status:")
	println("=================")

	// Query daemon for GPU info
	resp := query_daemon(config, "STATUS") or {
		eprintln("Error: Failed to connect to daemon")
		return
	}

	for gpu in resp.gpus {
		enabled_str := if gpu.enabled { "enabled" } else { "disabled" }
		println("GPU ${gpu.index}: ${gpu.name}")
		println("  Vendor: ${gpu.vendor}")
		println("  VRAM: ${gpu.vram_mb} MB")
		println("  Utilization: ${gpu.util_pct}%")
		println("  Temperature: ${gpu.temp_c}°C")
		println("  Power: ${gpu.power_w}W")
		println("  State: ${enabled_str}")
		println("")
	}
}

fn cmd_list_gpus(config Config) {
	resp := query_daemon(config, "list-gpus") or {
		eprintln("Error: Failed to connect to daemon")
		return
	}

	println("Detected GPUs:")
	for gpu in resp.gpus {
		println("  [${gpu.index}] ${gpu.name} (${gpu.vendor}) - ${gpu.vram_mb}MB VRAM")
	}
}

fn cmd_create_group(config Config, args []string) {
	if args.len == 0 {
		eprintln("Error: GPU indices required")
		return
	}
	mut gpu_list := ""
	for arg in args {
		gpu_list += "${arg} "
	}
	println("Creating group with GPUs: ${gpu_list}")
	// Would send to daemon via IPC
}

fn cmd_set_power(config Config, profile string) {
	println("Setting power profile to: ${profile}")
	// Would send to daemon via IPC
}

fn cmd_set_curve(config Config, path string) {
	mut f := os.open(path) or {
		eprintln("Error: Cannot open power curve file: ${path}")
		return
	}
	defer { f.close() }

	mut content := f.read() or { "" }
	if content.len == 0 {
		eprintln("Error: Power curve file is empty")
		return
	}

	// Parse and apply power curve
	println("Loaded power curve from ${path}")
	// Would send to daemon via IPC
}

fn cmd_set_clock(config Config, min_clock string, max_clock string) {
	if min_clock.len == 0 || max_clock.len == 0 {
		eprintln("Error: min and max clock values required")
		return
	}
	println("Setting clock limits: min=${min_clock}MHz, max=${max_clock}MHz")
	// Would send to daemon via IPC
}

fn cmd_monitor(config Config) {
	println("Starting live monitoring...")
	println("Press Ctrl+C to stop")
	// Would launch ncurses interface - for now just poll status
	for i := 0; i < 5; i++ {
		cmd_status(config)
		time.sleep_ms(1000) // 1 second
	}
}

fn cmd_logs(config Config) {
	// Tail /var/log/mvgal/
	mut f := os.open("/var/log/mvgal/daemon.log") or {
		eprintln("Cannot open log file: /var/log/mvgal/daemon.log")
		return
	}
	defer { f.close() }

	for line in f.scan_lines() {
		println(line)
	}
}

fn cmd_dkms_install(config Config) {
	if !config.force {
		println("This will install kernel modules. Run with --sudo or as root.")
	}
	// Use pkexec for privileged operation
	os.system("pkexec dkms install mvgal/0.3.0") or {}
}

fn cmd_dkms_remove(config Config) {
	if !config.force {
		println("This will remove kernel modules. Run with --sudo or as root.")
	}
	// Use pkexec for privileged operation
	os.system("pkexec dkms remove mvgal/0.3.0 --all") or {}
}

fn query_daemon(config Config, query string) ?MvgalResponse {
	mut conn := connect_socket(config.socket_path) or {
		// Try reading from sysfs fallback
		return query_sysfs(query) or { return error("Failed to connect to daemon or sysfs") }
	}
	defer { conn.close() }

	resp_str := send_command(mut conn, query) or { "" }

	// Parse response - simplified JSON-like format
	mut resp := MvgalResponse{}

	// Basic parsing for demonstration
	if resp_str.contains("gpu_count") {
		// Would parse actual JSON response
		resp.daemon_running = true
	}

	return resp
}

fn query_sysfs(query string) ?MvgalResponse {
	mut resp := MvgalResponse{}

	// Check if sysfs exists and kernel module is loaded
	if !os.exists("/sys/class/mvgal/mvgal0/") {
		return error("Kernel module not loaded")
	}

	resp.daemon_running = false
	return resp
}

fn main() {
	mut config := Config{}

	flag.boolean(&config.verbose, "verbose", false, "Enable verbose output")
	flag.boolean(&config.force, "force", false, "Force operation")
	flag.string(&config.socket_path, "socket", default_socket, "Socket path")

	flag.parse()

	if flag.helped() {
		print_usage()
		exit(0)
	}

	if flag.versioned() {
		get_version()
		exit(0)
	}

	args := flag.args()
	if args.len == 0 {
		print_usage()
		exit(1)
	}

	cmd := args[0]

	match cmd {
		"status" {
			cmd_status(config)
		}
		"list-gpus" {
			cmd_list_gpus(config)
		}
		"monitor" {
			cmd_monitor(config)
		}
		"logs" {
			cmd_logs(config)
		}
		"create-group" {
			if args.len < 2 {
				eprintln("Error: GPU indices required")
			} else {
				cmd_create_group(config, args[1..])
			}
		}
		"set-power" {
			if args.len < 2 {
				eprintln("Error: Profile name required")
			} else {
				cmd_set_power(config, args[1])
			}
		}
		"set-curve" {
			if args.len < 2 {
				eprintln("Error: Power curve file path required")
			} else {
				cmd_set_curve(config, args[1])
			}
		}
		"set-clock" {
			if args.len < 3 {
				eprintln("Error: min and max clock values required")
			} else {
				cmd_set_clock(config, args[1], args[2])
			}
		}
		"dkms-install" {
			cmd_dkms_install(config)
		}
		"dkms-remove" {
			cmd_dkms_remove(config)
		}
		"-h", "--help" {
			print_usage()
		}
		"-v", "--version" {
			get_version()
		}
		else {
			eprintln("Unknown command: ${cmd}")
			print_usage()
			exit(1)
		}
	}
}
