package handler

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"strings"

	"github.com/go-playground/validator/v10"
)

// ─── Pagination ────────────────────────────────────────────────────────────────

const (
	defaultPage     = 1
	defaultPageSize = 20
	maxPageSize     = 100
)

// parsePagination extracts page and pageSize query params from the request.
func parsePagination(r *http.Request) (page, pageSize int) {
	page = defaultPage
	pageSize = defaultPageSize

	if p := r.URL.Query().Get("page"); p != "" {
		if n, err := strconv.Atoi(p); err == nil && n > 0 {
			page = n
		}
	}
	if ps := r.URL.Query().Get("pageSize"); ps != "" {
		if n, err := strconv.Atoi(ps); err == nil && n > 0 {
			if n > maxPageSize {
				n = maxPageSize
			}
			pageSize = n
		}
	}
	return page, pageSize
}

// paginateSlice computes the start and end indexes for a page of `total` items.
// Bounds are clamped to [0, total].
func paginateSlice(total, page, pageSize int) (start, end int) {
	start = (page - 1) * pageSize
	if start > total {
		start = total
	}
	end = start + pageSize
	if end > total {
		end = total
	}
	return start, end
}

// ─── JSON Helpers ─────────────────────────────────────────────────────────────

// writeJSON marshals v as JSON and writes it to w with the given status code.
func writeJSON(w http.ResponseWriter, status int, v any) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	if v == nil {
		return
	}
	if err := json.NewEncoder(w).Encode(v); err != nil {
		http.Error(w, `{"error":"internal encoding error"}`, http.StatusInternalServerError)
	}
}

// ─── Validation ───────────────────────────────────────────────────────────────

// validationErrors converts a validator.ValidationErrors into a string map
// suitable for the ErrorResponse details field.
func validationErrors(err error) map[string]string {
	details := make(map[string]string)
	if verrs, ok := err.(validator.ValidationErrors); ok {
		for _, fe := range verrs {
			field := strings.ToLower(fe.Field())
			details[field] = fieldError(fe)
		}
	}
	return details
}

func fieldError(fe validator.FieldError) string {
	switch fe.Tag() {
	case "required":
		return "this field is required"
	case "min":
		return fmt.Sprintf("must be at least %s characters", fe.Param())
	case "max":
		return fmt.Sprintf("must be at most %s characters", fe.Param())
	default:
		return fmt.Sprintf("failed validation: %s", fe.Tag())
	}
}

// validateAgentStatus is a custom validator for AgentStatus values.
func validateAgentStatus(fl validator.FieldLevel) bool {
	if status, ok := fl.Field().Interface().(interface {
		IsValid() bool
	}); ok {
		return status.IsValid()
	}
	return false
}
