//go:build linux
// +build linux

package client

import (
	"fmt"
	"log"
	"net"
	"os/exec"
	"time"

	"tailscale-clone/internal/types"
	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)

// Linux-specific WireGuard interface management
func (c *Client) createInterface() error {
	// Check if interface already exists
	_, err := c.wgClient.Device(c.interfaceName)
	if err == nil {
		log.Printf("Interface %s already exists", c.interfaceName)
		return nil
	}

	// Create interface using ip command
	cmd := exec.Command("ip", "link", "add", c.interfaceName, "type", "wireguard")
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("failed to create WireGuard interface: %v", err)
	}

	// Bring interface up
	cmd = exec.Command("ip", "link", "set", c.interfaceName, "up")
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("failed to bring interface up: %v", err)
	}

	return nil
}

func (c *Client) setupSubnetRouting() error {
	if !c.isSubnetRouter || len(c.subnets) == 0 {
		return nil
	}

	// Enable IP forwarding
	cmd := exec.Command("sysctl", "-w", "net.ipv4.ip_forward=1")
	if err := cmd.Run(); err != nil {
		log.Printf("Warning: Failed to enable IP forwarding: %v", err)
	}

	// Add routes for advertised subnets
	for _, subnet := range c.subnets {
		cmd := exec.Command("ip", "route", "add", subnet, "dev", c.interfaceName)
		if err := cmd.Run(); err != nil {
			log.Printf("Warning: Failed to add route for %s: %v", subnet, err)
		}
	}

	log.Printf("Subnet routing setup complete for: %v", c.subnets)
	return nil
}

func (c *Client) updateSubnetRouting() error {
	// Remove old routes
	cmd := exec.Command("ip", "route", "flush", "table", "main")
	if err := cmd.Run(); err != nil {
		log.Printf("Warning: Failed to flush routes: %v", err)
	}

	// Add routes for each subnet router
	for _, route := range c.subnetRoutes {
		if !route.Active {
			continue
		}

		// Find the peer for this subnet router
		device, err := c.wgClient.Device(c.interfaceName)
		if err != nil {
			continue
		}

		for _, peer := range device.Peers {
			// This is a simplified approach - in a real implementation,
			// you'd need to match the peer by public key or node ID
			for _, subnet := range route.Subnets {
				cmd := exec.Command("ip", "route", "add", subnet, "via", peer.Endpoint.IP.String())
				if err := cmd.Run(); err != nil {
					log.Printf("Warning: Failed to add route for %s via %s: %v", subnet, peer.Endpoint.IP, err)
				}
			}
		}
	}

	return nil
}

// Linux-specific interface configuration
func (c *Client) configureInterfacePlatform(networkCIDR string, peers []types.Peer) error {
	// Parse private key
	privateKeyBytes, err := hexToBytes(c.privateKey)
	if err != nil {
		return fmt.Errorf("invalid private key: %v", err)
	}

	// Set private key
	key, err := wgtypes.NewKey(privateKeyBytes)
	if err != nil {
		return fmt.Errorf("failed to create key: %v", err)
	}

	// Configure device
	cfg := wgtypes.Config{
		PrivateKey: &key,
		ListenPort: nil, // Let WireGuard choose a random port
	}

	if err := c.wgClient.ConfigureDevice(c.interfaceName, cfg); err != nil {
		return fmt.Errorf("failed to configure device: %v", err)
	}

	// Add IP address
	cmd := exec.Command("ip", "addr", "add", fmt.Sprintf("%s/24", c.ip), "dev", c.interfaceName)
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("failed to add IP address: %v", err)
	}

	// Add peers
	return c.updateWireGuardPeers(peers)
} 