package network

import (
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"strings"
)

// IsVLAN reports whether name is a VLAN interface (e.g. "eth0.100").
func IsVLAN(name string) bool {
	idx := strings.LastIndex(name, ".")
	if idx <= 0 {
		return false
	}
	suffix := name[idx+1:]
	if suffix == "" {
		return false
	}
	_, err := strconv.Atoi(suffix)
	return err == nil
}

// VLANParent returns the parent interface (e.g. "eth0.100" → "eth0").
func VLANParent(name string) string {
	idx := strings.LastIndex(name, ".")
	if idx < 0 {
		return ""
	}
	return name[:idx]
}

// VLANId returns the VLAN ID (e.g. "eth0.100" → 100).
func VLANId(name string) int {
	idx := strings.LastIndex(name, ".")
	if idx < 0 {
		return 0
	}
	id, _ := strconv.Atoi(name[idx+1:])
	return id
}

// EnsureVLANExists creates the VLAN interface in the kernel if it doesn't exist.
func EnsureVLANExists(name string) error {
	if _, err := os.Stat("/sys/class/net/" + name); err == nil {
		return nil
	}
	parent := VLANParent(name)
	id := VLANId(name)
	if parent == "" || id == 0 {
		return fmt.Errorf("invalid VLAN name: %s", name)
	}
	out, err := exec.Command("ip", "link", "add", "link", parent,
		"name", name, "type", "vlan", "id", strconv.Itoa(id)).CombinedOutput()
	if err != nil {
		return fmt.Errorf("ip link add %s: %s", name, strings.TrimSpace(string(out)))
	}
	return nil
}

// DeleteVLAN brings down and removes a VLAN interface and its /etc/network/interfaces stanza.
func DeleteVLAN(name string) error {
	_ = IfDown(name)
	if _, err := os.Stat("/sys/class/net/" + name); err == nil {
		out, err2 := exec.Command("ip", "link", "delete", name).CombinedOutput()
		if err2 != nil {
			return fmt.Errorf("ip link delete %s: %s", name, strings.TrimSpace(string(out)))
		}
	}
	configs, err := ParseConfig()
	if err != nil {
		return err
	}
	if _, ok := configs[name]; ok {
		delete(configs, name)
		return WriteConfig(configs)
	}
	return nil
}
