package main

import (
	"fmt"
	"io/ioutil"
	"net"
	"path/filepath"

	"github.com/charmbracelet/lipgloss"
	"github.com/vishvananda/netlink"
	"github.com/vishvananda/netns"
	"golang.org/x/sys/unix"
)

func main() {
	headerStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("63"))
	ipStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("203"))
	upStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("42"))
	downStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("196"))
	addrStyle := lipgloss.NewStyle().Faint(true)
	infoStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("33"))

	origNS, err := netns.Get()
	if err != nil {
		fmt.Println("Error getting current namespace:", err)
		return
	}
	defer origNS.Close()

	links, err := netlink.LinkList()
	if err != nil {
		fmt.Println("Error listing links:", err)
		return
	}

	for _, link := range links {
		attrs := link.Attrs()
		if attrs == nil {
			continue
		}

		state := downStyle.Render("DOWN")
		if attrs.Flags&net.FlagUp != 0 {
			state = upStyle.Render("UP")
		}

		fmt.Print(headerStyle.Render(attrs.Name), " ")
		fmt.Printf(addrStyle.Render(" %s"), attrs.HardwareAddr)
		fmt.Printf(addrStyle.Render(" %d"), attrs.MTU)
		fmt.Printf(" %s\n", state)

		addrs, err := netlink.AddrList(link, unix.AF_INET)
		if err == nil {
			for _, addr := range addrs {
				fmt.Println("  ", ipStyle.Render(addr.IPNet.String()))
			}
		}

		if link.Type() != "veth" {
			fmt.Println()
			continue
		}

		fmt.Println("  ", infoStyle.Render("Veth interface"))

		peerFound := false
		netnsDir := "/var/run/netns/"
		entries, err := ioutil.ReadDir(netnsDir)
		if err != nil {
			fmt.Println("  ", infoStyle.Render("Could not scan netns dir"))
		} else {
			for _, entry := range entries {
				nsPath := filepath.Join(netnsDir, entry.Name())

				nsHandle, err := netns.GetFromPath(nsPath)
				if err != nil {
					continue
				}

				if err := netns.Set(nsHandle); err != nil {
					nsHandle.Close()
					continue
				}

				remoteLinks, err := netlink.LinkList()
				if err == nil {
					for _, rl := range remoteLinks {
						if rl.Type() == "veth" && rl.Attrs().ParentIndex == attrs.Index {
							fmt.Println("  ", infoStyle.Render("Peer in namespace:"), entry.Name(), "as", rl.Attrs().Name)

							// Show IPs on peer
							peerAddrs, err := netlink.AddrList(rl, unix.AF_INET)
							if err == nil {
								for _, pa := range peerAddrs {
									fmt.Println("     ", ipStyle.Render(pa.IPNet.String()))
								}
							}

							fmt.Println("  ", infoStyle.Render("Interfaces in namespace:"), entry.Name())
							for _, intf := range remoteLinks {
								intfState := downStyle.Render("DOWN")
								if intf.Attrs().Flags&net.FlagUp != 0 {
									intfState = upStyle.Render("UP")
								}
								fmt.Printf("     %s %s\n", headerStyle.Render(intf.Attrs().Name), intfState)

								nsAddrs, err := netlink.AddrList(intf, unix.AF_INET)
								if err == nil {
									for _, addr := range nsAddrs {
										fmt.Println("       ", ipStyle.Render(addr.IPNet.String()))
									}
								}
							}

							peerFound = true
				routes, _ := netlink.RouteList(nil, unix.AF_INET)
				if len(routes) > 0 {
					fmt.Println("  ", infoStyle.Render("Routes in namespace:"), entry.Name())
					for _, route := range routes {
						dst := "default"
						if route.Dst != nil {
							dst = route.Dst.String()
						}
						via := ""
						if route.Gw != nil {
							via = "via " + route.Gw.String()
						}
						dev := ""
						if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil {
							dev = "dev " + link.Attrs().Name
						}
						src := ""
						if route.Src != nil {
							src = "src " + route.Src.String()
						}
						fmt.Printf("     %s %s %s %s\n", dst, via, dev, src)
					}
				}
							break
						}
					}
				}

				nsHandle.Close()
				netns.Set(origNS)

				
				if peerFound {
					break
				}
			}
		}

		if !peerFound {
			fmt.Println("  ", infoStyle.Render("Peer not found — may be deleted or hidden"))
		}

		fmt.Println()
	}
	fmt.Println(headerStyle.Render("Routes in main namespace:"))
	mainRoutes, err := netlink.RouteList(nil, unix.AF_INET)
	if err == nil {
		for _, route := range mainRoutes {
			var dst string
			if route.Dst == nil {
				dst = "default"
			} else {
				dst = route.Dst.String()
			}
	
			via := ""
			if route.Gw != nil {
				via = "via " + route.Gw.String()
			}
	
			dev := ""
			if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil {
				dev = "dev " + link.Attrs().Name
			}
			src := ""
			if route.Src != nil {
				src = "src " + route.Src.String()
			}
	
			fmt.Printf("  %s %s %s %s\n", dst, via, dev, src)
		}
	}
	fmt.Println()

}

