package handlers

import (
	"encoding/json"
	"net/http"

	"alpine-router/config"
	"alpine-router/dhcp"
	"alpine-router/network"
)

func HandleDHCPStatus(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		fail(w, http.StatusMethodNotAllowed, "method not allowed")
		return
	}

	installed := dhcp.IsInstalled()
	running := false
	if installed {
		running = dhcp.ServiceStatus()
	}

	ok(w, map[string]interface{}{
		"installed": installed,
		"running":   running,
	})
}

type ifaceInfo struct {
	Name    string `json:"name"`
	IPv4    string `json:"ipv4"`
	Netmask string `json:"ipv4_mask"`
	HasGW   bool   `json:"has_gateway"`
}

func HandleDHCPConfigGet(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		fail(w, http.StatusMethodNotAllowed, "method not allowed")
		return
	}

	cfg, err := dhcp.Load()
	if err != nil {
		fail(w, http.StatusInternalServerError, err.Error())
		return
	}

	names, _ := network.GetInterfaces()
	fileCfg, _ := network.ParseConfig()

	ifaces := []ifaceInfo{}
	for _, name := range names {
		if name == "lo" {
			continue
		}
		s, err := network.GetInterfaceStats(name)
		if err != nil {
			continue
		}
		hasGW := s.Gateway != ""
		if ncfg, exists := fileCfg[name]; exists && ncfg.Gateway != "" {
			hasGW = true
		}
		ifaces = append(ifaces, ifaceInfo{
			Name:    name,
			IPv4:    s.IPv4,
			Netmask: s.IPv4Mask,
			HasGW:   hasGW,
		})
	}

	ok(w, map[string]interface{}{
		"config":     cfg,
		"interfaces": ifaces,
	})
}

func HandleDHCPConfigSave(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		fail(w, http.StatusMethodNotAllowed, "method not allowed")
		return
	}

	var cfg dhcp.Config
	if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
		fail(w, http.StatusBadRequest, "invalid json: "+err.Error())
		return
	}
	if cfg.Pools == nil {
		cfg.Pools = []dhcp.Pool{}
	}
	if err := dhcp.Save(&cfg); err != nil {
		fail(w, http.StatusInternalServerError, err.Error())
		return
	}

	appCfg, err := config.Load()
	if err != nil {
		fail(w, http.StatusInternalServerError, "load config.yaml: "+err.Error())
		return
	}
	appCfg.DHCP.Enabled = cfg.Enabled
	appCfg.DHCP.Pools = make([]config.DHCPPool, len(cfg.Pools))
	for i, p := range cfg.Pools {
		appCfg.DHCP.Pools[i] = config.DHCPPool{
			Interface:  p.Interface,
			Enabled:    p.Enabled,
			Subnet:     p.Subnet,
			Netmask:    p.Netmask,
			RangeStart: p.RangeStart,
			RangeEnd:   p.RangeEnd,
			Router:     p.Router,
			DNS:        p.DNS,
			LeaseTime:  p.LeaseTime,
		}
	}
	if err := config.Save(appCfg); err != nil {
		fail(w, http.StatusInternalServerError, "save config.yaml: "+err.Error())
		return
	}

	ok(w, map[string]string{"message": "saved"})
}

func HandleDHCPApply(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		fail(w, http.StatusMethodNotAllowed, "method not allowed")
		return
	}

	if !dhcp.IsInstalled() {
		fail(w, http.StatusBadRequest, "dnsmasq не установлен — выполните: apk add dnsmasq")
		return
	}

	cfg, err := dhcp.Load()
	if err != nil {
		fail(w, http.StatusInternalServerError, err.Error())
		return
	}

	if err := dhcp.WriteConfigs(cfg); err != nil {
		fail(w, http.StatusInternalServerError, err.Error())
		return
	}

	if cfg.Enabled {
		if err := dhcp.ServiceRestart(); err != nil {
			fail(w, http.StatusInternalServerError, err.Error())
			return
		}
	} else {
		_ = dhcp.ServiceStop()
	}

	ok(w, map[string]string{"message": "applied"})
}