package handlers

import (
	"net/http"
	"strconv"

	"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"
)

// PortfolioHandlers handles portfolio HTTP requests
type PortfolioHandlers struct {
	store *portfolio.Store
}

// NewPortfolioHandlers creates new portfolio handlers
func NewPortfolioHandlers(store *portfolio.Store) *PortfolioHandlers {
	return &PortfolioHandlers{store: store}
}

// ============================================================================
// Portfolio CRUD
// ============================================================================

// CreatePortfolio creates a new portfolio
// POST /sdk/v1/portfolios
func (h *PortfolioHandlers) CreatePortfolio(c *gin.Context) {
	var req portfolio.CreatePortfolioRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	tenantID := rbac.GetTenantID(c)
	userID := rbac.GetUserID(c)

	p := &portfolio.Portfolio{
		TenantID:     tenantID,
		Name:         req.Name,
		Description:  req.Description,
		Status:       portfolio.PortfolioStatusDraft,
		Department:   req.Department,
		BusinessUnit: req.BusinessUnit,
		Owner:        req.Owner,
		OwnerEmail:   req.OwnerEmail,
		Settings:     req.Settings,
		CreatedBy:    userID,
	}

	if !p.Settings.AutoUpdateMetrics {
		p.Settings.AutoUpdateMetrics = true
	}

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

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

// ListPortfolios lists portfolios
// GET /sdk/v1/portfolios
func (h *PortfolioHandlers) ListPortfolios(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

	filters := &portfolio.PortfolioFilters{
		Limit: 50,
	}

	if status := c.Query("status"); status != "" {
		filters.Status = portfolio.PortfolioStatus(status)
	}
	if department := c.Query("department"); department != "" {
		filters.Department = department
	}
	if businessUnit := c.Query("business_unit"); businessUnit != "" {
		filters.BusinessUnit = businessUnit
	}
	if owner := c.Query("owner"); owner != "" {
		filters.Owner = owner
	}
	if limit := c.Query("limit"); limit != "" {
		if l, err := strconv.Atoi(limit); err == nil {
			filters.Limit = l
		}
	}
	if offset := c.Query("offset"); offset != "" {
		if o, err := strconv.Atoi(offset); err == nil {
			filters.Offset = o
		}
	}

	portfolios, err := h.store.ListPortfolios(c.Request.Context(), tenantID, filters)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

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

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

	summary, err := h.store.GetPortfolioSummary(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if summary == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "portfolio not found"})
		return
	}

	stats, _ := h.store.GetPortfolioStats(c.Request.Context(), id)

	c.JSON(http.StatusOK, gin.H{
		"portfolio":         summary.Portfolio,
		"items":             summary.Items,
		"risk_distribution": summary.RiskDistribution,
		"feasibility_dist":  summary.FeasibilityDist,
		"stats":             stats,
	})
}

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

	p, err := h.store.GetPortfolio(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if p == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "portfolio not found"})
		return
	}

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

	if req.Name != "" {
		p.Name = req.Name
	}
	if req.Description != "" {
		p.Description = req.Description
	}
	if req.Status != "" {
		p.Status = req.Status
	}
	if req.Department != "" {
		p.Department = req.Department
	}
	if req.BusinessUnit != "" {
		p.BusinessUnit = req.BusinessUnit
	}
	if req.Owner != "" {
		p.Owner = req.Owner
	}
	if req.OwnerEmail != "" {
		p.OwnerEmail = req.OwnerEmail
	}
	if req.Settings != nil {
		p.Settings = *req.Settings
	}

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

	c.JSON(http.StatusOK, gin.H{"portfolio": p})
}

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

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

	c.JSON(http.StatusOK, gin.H{"message": "portfolio deleted"})
}
