package handlers

import (
	"net/http"

	"github.com/breakpilot/ai-compliance-sdk/internal/portfolio"
	"github.com/breakpilot/ai-compliance-sdk/internal/rbac"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// ============================================================================
// Portfolio Items
// ============================================================================

// AddItem adds an item to a portfolio
// POST /sdk/v1/portfolios/:id/items
func (h *PortfolioHandlers) AddItem(c *gin.Context) {
	portfolioID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid portfolio ID"})
		return
	}

	var req portfolio.AddItemRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	userID := rbac.GetUserID(c)

	item := &portfolio.PortfolioItem{
		PortfolioID: portfolioID,
		ItemType:    req.ItemType,
		ItemID:      req.ItemID,
		Tags:        req.Tags,
		Notes:       req.Notes,
		AddedBy:     userID,
	}

	if err := h.store.AddItem(c.Request.Context(), item); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{"item": item})
}

// ListItems lists items in a portfolio
// GET /sdk/v1/portfolios/:id/items
func (h *PortfolioHandlers) ListItems(c *gin.Context) {
	portfolioID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid portfolio ID"})
		return
	}

	var itemType *portfolio.ItemType
	if t := c.Query("type"); t != "" {
		it := portfolio.ItemType(t)
		itemType = &it
	}

	items, err := h.store.ListItems(c.Request.Context(), portfolioID, itemType)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"items": items,
		"total": len(items),
	})
}

// BulkAddItems adds multiple items to a portfolio
// POST /sdk/v1/portfolios/:id/items/bulk
func (h *PortfolioHandlers) BulkAddItems(c *gin.Context) {
	portfolioID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid portfolio ID"})
		return
	}

	var req portfolio.BulkAddItemsRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	userID := rbac.GetUserID(c)

	items := make([]portfolio.PortfolioItem, len(req.Items))
	for i, r := range req.Items {
		items[i] = portfolio.PortfolioItem{
			ItemType: r.ItemType,
			ItemID:   r.ItemID,
			Tags:     r.Tags,
			Notes:    r.Notes,
		}
	}

	result, err := h.store.BulkAddItems(c.Request.Context(), portfolioID, items, userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, result)
}

// RemoveItem removes an item from a portfolio
// DELETE /sdk/v1/portfolios/:id/items/:itemId
func (h *PortfolioHandlers) RemoveItem(c *gin.Context) {
	itemID, err := uuid.Parse(c.Param("itemId"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid item ID"})
		return
	}

	if err := h.store.RemoveItem(c.Request.Context(), itemID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "item removed"})
}

// ReorderItems updates the order of items
// PUT /sdk/v1/portfolios/:id/items/order
func (h *PortfolioHandlers) ReorderItems(c *gin.Context) {
	portfolioID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid portfolio ID"})
		return
	}

	var req struct {
		ItemIDs []uuid.UUID `json:"item_ids"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if err := h.store.UpdateItemOrder(c.Request.Context(), portfolioID, req.ItemIDs); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "items reordered"})
}

// ============================================================================
// Merge Operations
// ============================================================================

// MergePortfolios merges two portfolios
// POST /sdk/v1/portfolios/merge
func (h *PortfolioHandlers) MergePortfolios(c *gin.Context) {
	var req portfolio.MergeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	source, err := h.store.GetPortfolio(c.Request.Context(), req.SourcePortfolioID)
	if err != nil || source == nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "source portfolio not found"})
		return
	}

	target, err := h.store.GetPortfolio(c.Request.Context(), req.TargetPortfolioID)
	if err != nil || target == nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "target portfolio not found"})
		return
	}

	if req.Strategy == "" {
		req.Strategy = portfolio.MergeStrategyUnion
	}

	userID := rbac.GetUserID(c)

	result, err := h.store.MergePortfolios(c.Request.Context(), &req, userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "portfolios merged",
		"result":  result,
	})
}
