package webui

import (
	"net"
	"net/http"
)

// blacklistPage lists both currently/recently blacklisted IPs (auto or manual) and the
// abuse-detection whitelist — global-admin only, since a blacklist entry isn't
// attributable to one domain the way a mailbox or relay-whitelist row is.
func (a *App) blacklistPage(w http.ResponseWriter, r *http.Request) {
	entries, err := a.DB.ListBlacklist()
	if err != nil {
		setFlash(w, "error", "Error loading blacklist")
	}
	whitelist, err := a.DB.ListAbuseWhitelist()
	if err != nil {
		setFlash(w, "error", "Error loading abuse whitelist")
	}
	a.render(w, r, "blacklist.html", M{"active": "blacklist", "entries": entries, "whitelist": whitelist})
}

// addBlacklistEntry is an admin-initiated manual block: fixed duration, no escalation.
func (a *App) addBlacklistEntry(w http.ResponseWriter, r *http.Request) {
	ip := r.FormValue("ip_address")
	reason := r.FormValue("reason")
	hours := atoi(r.FormValue("hours"))

	if net.ParseIP(ip) == nil || hours <= 0 {
		setFlash(w, "error", "A valid IP address and a positive duration in hours are required")
		http.Redirect(w, r, Prefix+"/blacklist", http.StatusFound)
		return
	}
	if err := a.DB.AddManualBlacklistEntry(ip, reason, hours); err != nil {
		setFlash(w, "error", "Error blacklisting IP")
	} else {
		setFlash(w, "success", "IP blacklisted")
	}
	http.Redirect(w, r, Prefix+"/blacklist", http.StatusFound)
}

func (a *App) removeBlacklistEntry(w http.ResponseWriter, r *http.Request) {
	if err := a.DB.RemoveBlacklistEntry(pathID(r)); err != nil {
		setFlash(w, "error", "Error removing blacklist entry")
	} else {
		setFlash(w, "success", "Blacklist entry removed")
	}
	http.Redirect(w, r, Prefix+"/blacklist", http.StatusFound)
}

// whitelistBlacklistedIP removes ip from the blacklist and adds it to the abuse
// whitelist in one action, so an admin can undo a false-positive auto-block without
// two separate trips.
func (a *App) whitelistBlacklistedIP(w http.ResponseWriter, r *http.Request) {
	id := pathID(r)
	entries, err := a.DB.ListBlacklist()
	if err != nil {
		setFlash(w, "error", "Error loading blacklist")
		http.Redirect(w, r, Prefix+"/blacklist", http.StatusFound)
		return
	}
	var ip string
	for _, e := range entries {
		if e.ID == id {
			ip = e.IPAddress
			break
		}
	}
	if ip == "" {
		http.NotFound(w, r)
		return
	}
	if err := a.DB.AddAbuseWhitelist(ip, "whitelisted from a blacklist entry"); err != nil {
		setFlash(w, "error", "Error whitelisting IP")
		http.Redirect(w, r, Prefix+"/blacklist", http.StatusFound)
		return
	}
	_ = a.DB.RemoveBlacklistEntry(id)
	setFlash(w, "success", ip+" whitelisted and removed from the blacklist")
	http.Redirect(w, r, Prefix+"/blacklist", http.StatusFound)
}

func (a *App) addAbuseWhitelistEntry(w http.ResponseWriter, r *http.Request) {
	ip := r.FormValue("ip_address")
	note := r.FormValue("note")
	if net.ParseIP(ip) == nil {
		setFlash(w, "error", "A valid IP address is required")
		http.Redirect(w, r, Prefix+"/blacklist", http.StatusFound)
		return
	}
	if err := a.DB.AddAbuseWhitelist(ip, note); err != nil {
		setFlash(w, "error", "Error adding to abuse whitelist")
	} else {
		setFlash(w, "success", "IP added to the abuse-detection whitelist")
	}
	http.Redirect(w, r, Prefix+"/blacklist", http.StatusFound)
}

func (a *App) removeAbuseWhitelistEntry(w http.ResponseWriter, r *http.Request) {
	if err := a.DB.RemoveAbuseWhitelist(pathID(r)); err != nil {
		setFlash(w, "error", "Error removing abuse whitelist entry")
	} else {
		setFlash(w, "success", "Removed from the abuse-detection whitelist")
	}
	http.Redirect(w, r, Prefix+"/blacklist", http.StatusFound)
}
