package agent

import (
	"net/http"
	"slices"
	"strconv"

	"github.com/gin-gonic/gin"

	"security-center-backend/internal/model"
	"security-center-backend/internal/pkg/response"
	"security-center-backend/internal/repository"
)

// List handles GET /agent/api-keys (P2-T6). Callers carrying the "admin"
// role list across owners via ListAll with the query filter; regular users
// only ever see their own keys via ListByOwner.
func (h *Handler) List(c *gin.Context) {
	claims := currentUser(c)
	if claims == nil {
		response.Error(c, http.StatusUnauthorized, "not authenticated")
		return
	}

	var (
		keys []*model.APIKey
		err  error
	)
	if slices.Contains(claims.Roles, "admin") {
		keys, err = h.repo.ListAll(c.Request.Context(), parseListFilter(c))
	} else {
		keys, err = h.repo.ListByOwner(c.Request.Context(), claims.UserID)
	}
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "failed to list api keys")
		return
	}

	items := make([]*APIKeyResponse, 0, len(keys))
	for _, key := range keys {
		items = append(items, toAPIKeyResponse(key))
	}
	response.Success(c, items)
}

// parseListFilter reads the admin list query params. Invalid page/page_size
// values are left at zero and clamped by the repository defaults.
func parseListFilter(c *gin.Context) repository.ListAPIKeysFilter {
	var filter repository.ListAPIKeysFilter
	if page, err := strconv.Atoi(c.Query("page")); err == nil {
		filter.Page = page
	}
	if pageSize, err := strconv.Atoi(c.Query("page_size")); err == nil {
		filter.PageSize = pageSize
	}
	if raw := c.Query("owner_user_id"); raw != "" {
		if ownerUserID, err := strconv.ParseUint(raw, 10, 64); err == nil {
			filter.OwnerUserID = &ownerUserID
		}
	}
	filter.Status = c.Query("status")
	return filter
}

// Get handles GET /agent/api-keys/:id (P2-T6). Admins may fetch any key via
// FindByID; regular users are owner-scoped via FindByIDForOwner and get 404
// for keys they do not own.
func (h *Handler) Get(c *gin.Context) {
	claims := currentUser(c)
	if claims == nil {
		response.Error(c, http.StatusUnauthorized, "not authenticated")
		return
	}

	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil || id == 0 {
		response.Error(c, http.StatusBadRequest, "invalid api key id")
		return
	}

	var key *model.APIKey
	if slices.Contains(claims.Roles, "admin") {
		key, err = h.repo.FindByID(c.Request.Context(), id)
	} else {
		key, err = h.repo.FindByIDForOwner(c.Request.Context(), id, claims.UserID)
	}
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "failed to get api key")
		return
	}
	if key == nil {
		response.Error(c, http.StatusNotFound, "api key not found")
		return
	}
	response.Success(c, toAPIKeyResponse(key))
}
