package handlers

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"go.uber.org/zap"
	"veza-backend-api/internal/core/marketplace"
)

// MarketplaceHandler gère les opérations de la marketplace
type MarketplaceHandler struct {
	service       marketplace.MarketplaceService
	commonHandler *CommonHandler
}

// NewMarketplaceHandler crée une nouvelle instance de MarketplaceHandler
func NewMarketplaceHandler(service marketplace.MarketplaceService, logger *zap.Logger) *MarketplaceHandler {
	return &MarketplaceHandler{
		service:       service,
		commonHandler: NewCommonHandler(logger),
	}
}

// CreateProductRequest DTO pour la création de produit
// GO-013: Validation améliorée avec tags go-validator
type CreateProductRequest struct {
	Title       string  `json:"title" binding:"required,min=3,max=200"`
	Description string  `json:"description" binding:"max=2000"`
	Price       float64 `json:"price" binding:"required,min=0,gt=0"`
	ProductType string  `json:"product_type" binding:"required,oneof=track pack service"`
	TrackID     string  `json:"track_id,omitempty" binding:"omitempty,uuid"` // UUID string
	LicenseType string  `json:"license_type,omitempty" binding:"omitempty,oneof=standard exclusive commercial"`
}

// CreateProduct gère la création d'un produit
// @Summary Create a new product
// @Description Create a product (Track, Pack, Service) for sale
// @Tags Marketplace
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param product body CreateProductRequest true "Product info"
// @Success 201 {object} marketplace.Product
// @Failure 400 {object} map[string]string
// @Failure 401 {object} map[string]string
// @Router /api/v1/marketplace/products [post]
func (h *MarketplaceHandler) CreateProduct(c *gin.Context) {
	userID := c.MustGet("user_id").(uuid.UUID)

	var req CreateProductRequest
	if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
		RespondWithAppError(c, appErr)
		return
	}

	product := &marketplace.Product{
		SellerID:    userID,
		Title:       req.Title,
		Description: req.Description,
		Price:       req.Price,
		ProductType: req.ProductType,
		LicenseType: marketplace.LicenseType(req.LicenseType),
		Status:      marketplace.ProductStatusActive, // Direct active for MVP
	}

	if req.TrackID != "" {
		trackUUID, err := uuid.Parse(req.TrackID)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid track_id format"})
			return
		}
		product.TrackID = &trackUUID
	}

	if err := h.service.CreateProduct(c.Request.Context(), product); err != nil {
		if err == marketplace.ErrInvalidSeller {
			c.JSON(http.StatusForbidden, gin.H{"error": "You do not own this track"})
			return
		}
		if err == marketplace.ErrTrackNotFound {
			c.JSON(http.StatusNotFound, gin.H{"error": "Track not found"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create product"})
		return
	}

	c.JSON(http.StatusCreated, product)
}

// CreateOrderRequest DTO pour la création de commande
type CreateOrderRequest struct {
	Items []struct {
		ProductID string `json:"product_id" binding:"required"`
	} `json:"items" binding:"required,min=1"`
}

// CreateOrder gère l'achat de produits
// @Summary Create a new order
// @Description Purchase products
// @Tags Marketplace
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param order body CreateOrderRequest true "Order items"
// @Success 201 {object} marketplace.Order
// @Failure 400 {object} map[string]string
// @Failure 401 {object} map[string]string
// @Router /api/v1/marketplace/orders [post]
func (h *MarketplaceHandler) CreateOrder(c *gin.Context) {
	buyerID := c.MustGet("user_id").(uuid.UUID)

	var req CreateOrderRequest
	if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
		RespondWithAppError(c, appErr)
		return
	}

	var items []marketplace.NewOrderItem
	for _, item := range req.Items {
		pid, err := uuid.Parse(item.ProductID)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product_id: " + item.ProductID})
			return
		}
		items = append(items, marketplace.NewOrderItem{ProductID: pid})
	}

	order, err := h.service.CreateOrder(c.Request.Context(), buyerID, items)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, order)
}

// GetDownloadURL récupère l'URL de téléchargement pour un achat
// @Summary Get download URL
// @Description Get a secure download URL for a purchased product
// @Tags Marketplace
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param product_id path string true "Product ID"
// @Success 200 {object} map[string]string
// @Failure 403 {object} map[string]string "No license"
// @Failure 404 {object} map[string]string
// @Router /api/v1/marketplace/download/{product_id} [get]
func (h *MarketplaceHandler) GetDownloadURL(c *gin.Context) {
	userID := c.MustGet("user_id").(uuid.UUID)
	productIDStr := c.Param("product_id")
	
	productID, err := uuid.Parse(productIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product_id"})
		return
	}

	url, err := h.service.GetDownloadURL(c.Request.Context(), userID, productID)
	if err != nil {
		if err == marketplace.ErrNoLicense {
			c.JSON(http.StatusForbidden, gin.H{"error": "No valid license for this product"})
			return
		}
		if err == marketplace.ErrTrackNotFound {
			c.JSON(http.StatusNotFound, gin.H{"error": "Track file not found"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get download URL"})
		return
	}

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

// ListProducts liste les produits
// @Summary List products
// @Description List marketplace products with filters
// @Tags Marketplace
// @Accept json
// @Produce json
// @Param status query string false "Product status"
// @Param seller_id query string false "Seller ID"
// @Success 200 {array} marketplace.Product
// @Router /api/v1/marketplace/products [get]
func (h *MarketplaceHandler) ListProducts(c *gin.Context) {
	filters := make(map[string]interface{})
	
	if status := c.Query("status"); status != "" {
		filters["status"] = status
	}
	if sellerID := c.Query("seller_id"); sellerID != "" {
		filters["seller_id"] = sellerID
	}

	products, err := h.service.ListProducts(c.Request.Context(), filters)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to list products"})
		return
	}

	c.JSON(http.StatusOK, products)
}
