package handlers

// team_package_settings.go — v0.2.0
//
// Team-admin endpoints for managing team-scoped package settings.
// These sit in the settings cascade between global (admin) and user.
// Only overridable keys (user_overridable != false) can be set at team scope.

import (
	"encoding/json"
	"strings"

	"github.com/gin-gonic/gin"

	"switchboard-core/store"
)

// TeamPackageSettingsHandler serves team-scoped package settings endpoints.
type TeamPackageSettingsHandler struct {
	stores store.Stores
}

func NewTeamPackageSettingsHandler(s store.Stores) *TeamPackageSettingsHandler {
	return &TeamPackageSettingsHandler{stores: s}
}

// GetTeamPackageSettings returns the team-scoped settings for a package,
// along with the overridable schema keys for the UI.
// GET /api/v1/teams/:teamId/packages/:id/settings
func (h *TeamPackageSettingsHandler) GetTeamPackageSettings(c *gin.Context) {
	teamID := c.Param("teamId")
	pkgID := c.Param("id")

	pkg, err := h.stores.Packages.Get(c.Request.Context(), pkgID)
	if err != nil || pkg == nil {
		c.JSON(404, gin.H{"error": "package not found"})
		return
	}

	// Parse schema and filter to overridable keys only
	schema := store.ParseSettingsSchema(pkg.Manifest)
	var overridableSchema []store.SettingSchema
	for _, s := range schema {
		if s.IsUserOverridable() {
			overridableSchema = append(overridableSchema, s)
		}
	}

	// Load current team values
	settings, err := h.stores.Packages.GetTeamSettings(c.Request.Context(), pkgID, teamID)
	if err != nil {
		settings = json.RawMessage("{}")
	}

	c.JSON(200, gin.H{
		"schema": overridableSchema,
		"values": json.RawMessage(settings),
	})
}

// UpdateTeamPackageSettings saves team-scoped overrides for a package.
// Non-overridable keys are stripped before saving.
// PUT /api/v1/teams/:teamId/packages/:id/settings
func (h *TeamPackageSettingsHandler) UpdateTeamPackageSettings(c *gin.Context) {
	teamID := c.Param("teamId")
	pkgID := c.Param("id")

	pkg, err := h.stores.Packages.Get(c.Request.Context(), pkgID)
	if err != nil || pkg == nil {
		c.JSON(404, gin.H{"error": "package not found"})
		return
	}

	var body struct {
		Settings json.RawMessage `json:"settings" binding:"required"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(400, gin.H{"error": "invalid request body"})
		return
	}

	// Parse and enforce user_overridable
	schema := store.ParseSettingsSchema(pkg.Manifest)
	var incoming map[string]any
	if err := json.Unmarshal(body.Settings, &incoming); err != nil {
		c.JSON(400, gin.H{"error": "settings must be a JSON object"})
		return
	}

	filtered, rejected := store.FilterOverridableKeys(incoming, schema)
	if len(filtered) == 0 && len(rejected) > 0 {
		c.JSON(400, gin.H{"error": "these settings cannot be overridden: " + strings.Join(rejected, ", ")})
		return
	}

	settingsJSON, err := json.Marshal(filtered)
	if err != nil {
		c.JSON(500, gin.H{"error": "failed to marshal settings"})
		return
	}

	if err := h.stores.Packages.SetTeamSettings(c.Request.Context(), pkgID, teamID, json.RawMessage(settingsJSON)); err != nil {
		c.JSON(500, gin.H{"error": "failed to save team settings"})
		return
	}

	c.JSON(200, gin.H{"ok": true, "rejected_keys": rejected})
}

// DeleteTeamPackageSettings removes team-scoped overrides for a package.
// DELETE /api/v1/teams/:teamId/packages/:id/settings
func (h *TeamPackageSettingsHandler) DeleteTeamPackageSettings(c *gin.Context) {
	teamID := c.Param("teamId")
	pkgID := c.Param("id")

	if err := h.stores.Packages.DeleteTeamSettings(c.Request.Context(), pkgID, teamID); err != nil {
		c.JSON(500, gin.H{"error": "failed to delete team settings"})
		return
	}

	c.JSON(200, gin.H{"ok": true})
}
