package handlers

// folders.go — Chat folder CRUD (v0.23.1)
//
// v0.29.0: Raw SQL replaced with FolderStore methods.

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

	"github.com/gin-gonic/gin"

	"chat-switchboard/models"
	"chat-switchboard/store"
)

type FolderHandler struct {
	stores store.Stores
}

func NewFolderHandler(s store.Stores) *FolderHandler {
	return &FolderHandler{stores: s}
}

func (h *FolderHandler) List(c *gin.Context) {
	userID := getUserID(c)

	folders, err := h.stores.Folders.List(c.Request.Context(), userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list folders"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": folders})
}

func (h *FolderHandler) Create(c *gin.Context) {
	userID := getUserID(c)
	var req struct {
		Name      string  `json:"name" binding:"required"`
		ParentID  *string `json:"parent_id"`
		SortOrder int     `json:"sort_order"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	req.Name = strings.TrimSpace(req.Name)
	if req.Name == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "name is required"})
		return
	}

	f := &models.Folder{
		UserID:    userID,
		Name:      req.Name,
		ParentID:  req.ParentID,
		SortOrder: req.SortOrder,
	}
	if err := h.stores.Folders.Create(c.Request.Context(), f); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create folder"})
		return
	}
	c.JSON(http.StatusCreated, gin.H{"folder": f})
}

func (h *FolderHandler) Update(c *gin.Context) {
	userID := getUserID(c)
	folderID := c.Param("id")

	// Read raw body to detect which fields were explicitly sent
	data, err := c.GetRawData()
	if err != nil || len(data) == 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"})
		return
	}
	var req struct {
		Name      string  `json:"name"`
		SortOrder *int    `json:"sort_order"`
		ParentID  *string `json:"parent_id"`
	}
	if err := json.Unmarshal(data, &req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	if req.Name != "" {
		req.Name = strings.TrimSpace(req.Name)
	}

	// Only update parent_id if it was explicitly present in the JSON
	var parentID **string
	var raw map[string]json.RawMessage
	_ = json.Unmarshal(data, &raw)
	if _, ok := raw["parent_id"]; ok {
		parentID = &req.ParentID
	}

	n, err := h.stores.Folders.Update(c.Request.Context(), folderID, userID, req.Name, req.SortOrder, parentID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update folder"})
		return
	}
	if n == 0 {
		c.JSON(http.StatusNotFound, gin.H{"error": "folder not found"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ok": true})
}

func (h *FolderHandler) Delete(c *gin.Context) {
	userID := getUserID(c)
	folderID := c.Param("id")

	// Unassign chats before deleting folder
	_ = h.stores.Folders.UnassignChannels(c.Request.Context(), folderID, userID)

	n, err := h.stores.Folders.Delete(c.Request.Context(), folderID, userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to delete folder"})
		return
	}
	if n == 0 {
		c.JSON(http.StatusNotFound, gin.H{"error": "folder not found"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ok": true})
}
