package handlers

import (
	"context"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	"crowdsec-dashy/internal/crowdsec"
)

// AlertsHandler manages the alerts page and its POST actions.
type AlertsHandler struct {
	deps Deps
}

func NewAlertsHandler(deps Deps) *AlertsHandler {
	return &AlertsHandler{deps: deps}
}

// AlertsData is passed to the alerts template.
type AlertsData struct {
	PageData
	Alerts []crowdsec.Alert
	Filter crowdsec.AlertFilter
}

// List renders the alerts list.
func (h *AlertsHandler) List(w http.ResponseWriter, r *http.Request) {
	ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second)
	defer cancel()

	filter := crowdsec.AlertFilter{
		Limit:    200,
		Scenario: r.URL.Query().Get("scenario"),
		IP:       r.URL.Query().Get("ip"),
		Since:    r.URL.Query().Get("since"),
	}

	alerts, err := h.deps.LAPI.ListAlerts(ctx, filter)
	if err != nil {
		h.deps.Renderer.RenderError(w, http.StatusBadGateway, "failed to fetch alerts")
		return
	}

	pd := NewPageData(r, "Alerts", h.deps.CLIAvailable, h.deps.PollInterval)
	if f := readFlash(r); f.Message != "" {
		pd.Flash = f
	}

	h.deps.Renderer.Render(w, "alerts", AlertsData{
		PageData: pd,
		Alerts:   alerts,
		Filter:   filter,
	})
}

// Delete processes alert deletion (POST; `id` field may repeat for bulk).
func (h *AlertsHandler) Delete(w http.ResponseWriter, r *http.Request) {
	r.Body = http.MaxBytesReader(w, r.Body, 4096)
	if err := r.ParseForm(); err != nil {
		flashRedirect(w, r, "/alerts", "error", "invalid form data")
		return
	}
	if !checkCSRF(r) {
		http.Error(w, "forbidden", http.StatusForbidden)
		return
	}

	ids := r.Form["id"]
	if len(ids) == 0 {
		flashRedirect(w, r, "/alerts", "error", "no alert selected")
		return
	}

	ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second)
	defer cancel()

	var errs []string
	deleted := 0
	for _, s := range ids {
		id, err := strconv.ParseInt(s, 10, 64)
		if err != nil || id <= 0 {
			errs = append(errs, fmt.Sprintf("invalid id: %q", s))
			continue
		}
		if err := h.deps.LAPI.DeleteAlert(ctx, id); err != nil {
			errs = append(errs, fmt.Sprintf("id %d: %v", id, err))
			continue
		}
		deleted++
	}

	if len(errs) > 0 {
		flashRedirect(w, r, "/alerts", "error", strings.Join(errs, "; "))
		return
	}

	flashRedirect(w, r, "/alerts", "success", fmt.Sprintf("%d alert(s) deleted", deleted))
}
