package handlers

import (
	"net/http"
	"strconv"

	"payment/internal/services"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// PackageHandler handles package-related HTTP requests
type PackageHandler struct {
	packageService *services.PackageService
}

// NewPackageHandler creates a new package handler
func NewPackageHandler(packageService *services.PackageService) *PackageHandler {
	return &PackageHandler{
		packageService: packageService,
	}
}

// CreatePackage creates a new internet package
func (h *PackageHandler) CreatePackage(c *gin.Context) {
	var req services.CreatePackageRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Get client ID from auth context
	clientID, exists := c.Get("client_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Client ID not found in context"})
		return
	}

	clientUUID := clientID.(uuid.UUID)
	req.ClientID = &clientUUID

	packageInfo, err := h.packageService.CreatePackage(c.Request.Context(), &req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"message": "Package created successfully",
		"data":    packageInfo,
	})
}

// GetPackages retrieves packages for a client with pagination
func (h *PackageHandler) GetPackages(c *gin.Context) {
	// Get client ID from auth context
	clientID, exists := c.Get("client_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Client ID not found in context"})
		return
	}

	// Parse query parameters
	activeOnly := c.Query("active_only") == "true"
	limit := 10 // default
	offset := 0

	if limitStr := c.Query("limit"); limitStr != "" {
		if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 {
			limit = parsedLimit
		}
	}
	if offsetStr := c.Query("offset"); offsetStr != "" {
		if parsedOffset, err := strconv.Atoi(offsetStr); err == nil && parsedOffset >= 0 {
			offset = parsedOffset
		}
	}

	packages, totalCount, err := h.packageService.GetPackages(c.Request.Context(), clientID.(uuid.UUID), activeOnly, limit, offset)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "Packages retrieved successfully",
		"data":    packages,
		"count":   len(packages),
		"total":   totalCount,
	})
}

// GetPackage retrieves a specific package
func (h *PackageHandler) GetPackage(c *gin.Context) {
	// Get client ID from auth context
	clientID, exists := c.Get("client_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Client ID not found in context"})
		return
	}

	// Get package ID from URL parameter
	packageIDStr := c.Param("id")
	packageID, err := uuid.Parse(packageIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid package ID"})
		return
	}

	packageInfo, err := h.packageService.GetPackage(c.Request.Context(), clientID.(uuid.UUID), packageID)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "Package retrieved successfully",
		"data":    packageInfo,
	})
}

// UpdatePackage updates an internet package
func (h *PackageHandler) UpdatePackage(c *gin.Context) {
	// Get client ID from auth context
	clientID, exists := c.Get("client_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Client ID not found in context"})
		return
	}

	// Get package ID from URL parameter
	packageIDStr := c.Param("id")
	packageID, err := uuid.Parse(packageIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid package ID"})
		return
	}

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

	packageInfo, err := h.packageService.UpdatePackage(c.Request.Context(), clientID.(uuid.UUID), packageID, &req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "Package updated successfully",
		"data":    packageInfo,
	})
}

// DeletePackage deletes an internet package
func (h *PackageHandler) DeletePackage(c *gin.Context) {
	// Get client ID from auth context
	clientID, exists := c.Get("client_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Client ID not found in context"})
		return
	}

	// Get package ID from URL parameter
	packageIDStr := c.Param("id")
	packageID, err := uuid.Parse(packageIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid package ID"})
		return
	}

	err = h.packageService.DeletePackage(c.Request.Context(), clientID.(uuid.UUID), packageID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

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

// GetPublicPackages retrieves active packages for public access (no auth required) with pagination
func (h *PackageHandler) GetPublicPackages(c *gin.Context) {
	// Get client ID from query parameter
	clientIDStr := c.Query("client_id")
	if clientIDStr == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "client_id query parameter is required"})
		return
	}

	clientID, err := uuid.Parse(clientIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid client ID"})
		return
	}

	// Parse pagination parameters
	limit := 10 // default
	offset := 0

	if limitStr := c.Query("limit"); limitStr != "" {
		if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 {
			limit = parsedLimit
		}
	}
	if offsetStr := c.Query("offset"); offsetStr != "" {
		if parsedOffset, err := strconv.Atoi(offsetStr); err == nil && parsedOffset >= 0 {
			offset = parsedOffset
		}
	}

	// Only return active packages for public access
	packages, totalCount, err := h.packageService.GetPackages(c.Request.Context(), clientID, true, limit, offset)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "Packages retrieved successfully",
		"data":    packages,
		"count":   len(packages),
		"total":   totalCount,
	})
}
