package handlers

import (
	"database/sql"
	"encoding/json"
	"io"
	"log"
	"net/http"

	"github.com/Molecule-AI/molecule-monorepo/platform/internal/db"
	"github.com/gin-gonic/gin"
)

type ConfigHandler struct{}

func NewConfigHandler() *ConfigHandler { return &ConfigHandler{} }

// Get handles GET /workspaces/:id/config
func (h *ConfigHandler) Get(c *gin.Context) {
	workspaceID := c.Param("id")

	var data []byte
	err := db.DB.QueryRowContext(c.Request.Context(),
		`SELECT data FROM workspace_config WHERE workspace_id = $1`,
		workspaceID,
	).Scan(&data)

	if err == sql.ErrNoRows {
		c.JSON(http.StatusOK, gin.H{"data": json.RawMessage("{}")})
		return
	}
	if err != nil {
		log.Printf("Config get error: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "query failed"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"data": json.RawMessage(data)})
}

// Patch handles PATCH /workspaces/:id/config
func (h *ConfigHandler) Patch(c *gin.Context) {
	workspaceID := c.Param("id")

	// 256 KiB cap: Postgres jsonb comfortably handles this and real
	// configs are <10 KiB. The cap blocks naive memory-exhaustion DoS
	// — a caller streaming a gigabyte of JSON would OOM the instance.
	const maxConfigBody = 256 << 10
	c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, maxConfigBody)
	body, err := io.ReadAll(c.Request.Body)
	if err != nil {
		c.JSON(http.StatusRequestEntityTooLarge, gin.H{"error": "body too large or unreadable"})
		return
	}

	if !json.Valid(body) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON"})
		return
	}

	_, err = db.DB.ExecContext(c.Request.Context(), `
		INSERT INTO workspace_config(workspace_id, data, updated_at)
		VALUES($1, $2::jsonb, NOW())
		ON CONFLICT(workspace_id) DO UPDATE
		SET data = workspace_config.data || $2::jsonb, updated_at = NOW()
	`, workspaceID, string(body))
	if err != nil {
		log.Printf("Config patch error: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update config"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"status": "updated"})
}
