package handlers

import (
	"net/http"
	"strconv"

	"github.com/labstack/echo/v4"
	"gorm.io/gorm"

	"github.com/treytartt/honeydue-api/internal/admin/dto"
	"github.com/treytartt/honeydue-api/internal/models"
)

// AdminFeatureBenefitHandler handles admin feature benefit management endpoints
type AdminFeatureBenefitHandler struct {
	db *gorm.DB
}

// NewAdminFeatureBenefitHandler creates a new admin feature benefit handler
func NewAdminFeatureBenefitHandler(db *gorm.DB) *AdminFeatureBenefitHandler {
	return &AdminFeatureBenefitHandler{db: db}
}

// FeatureBenefitResponse represents a feature benefit in API responses
type FeatureBenefitResponse struct {
	ID           uint   `json:"id"`
	FeatureName  string `json:"feature_name"`
	FreeTierText string `json:"free_tier_text"`
	ProTierText  string `json:"pro_tier_text"`
	DisplayOrder int    `json:"display_order"`
	IsActive     bool   `json:"is_active"`
	CreatedAt    string `json:"created_at"`
	UpdatedAt    string `json:"updated_at"`
}

// List handles GET /api/admin/feature-benefits
func (h *AdminFeatureBenefitHandler) List(c echo.Context) error {
	var filters dto.PaginationParams
	if err := c.Bind(&filters); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid request body"})
	}

	var benefits []models.FeatureBenefit
	var total int64

	query := h.db.Model(&models.FeatureBenefit{})

	if filters.Search != "" {
		search := "%" + filters.Search + "%"
		query = query.Where("feature_name ILIKE ? OR free_tier_text ILIKE ? OR pro_tier_text ILIKE ?", search, search, search)
	}

	query.Count(&total)

	// Apply sorting (allowlist prevents SQL injection via sort_by parameter)
	sortBy := filters.GetSafeSortBy([]string{
		"id", "feature_name", "display_order", "is_active", "created_at", "updated_at",
	}, "display_order")
	query = query.Order(sortBy + " " + filters.GetSortDir())
	query = query.Offset(filters.GetOffset()).Limit(filters.GetPerPage())

	if err := query.Find(&benefits).Error; err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to fetch feature benefits"})
	}

	responses := make([]FeatureBenefitResponse, len(benefits))
	for i, b := range benefits {
		responses[i] = FeatureBenefitResponse{
			ID:           b.ID,
			FeatureName:  b.FeatureName,
			FreeTierText: b.FreeTierText,
			ProTierText:  b.ProTierText,
			DisplayOrder: b.DisplayOrder,
			IsActive:     b.IsActive,
			CreatedAt:    b.CreatedAt.Format("2006-01-02T15:04:05Z"),
			UpdatedAt:    b.UpdatedAt.Format("2006-01-02T15:04:05Z"),
		}
	}

	return c.JSON(http.StatusOK, dto.NewPaginatedResponse(responses, total, filters.GetPage(), filters.GetPerPage()))
}

// Get handles GET /api/admin/feature-benefits/:id
func (h *AdminFeatureBenefitHandler) Get(c echo.Context) error {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid ID"})
	}

	var benefit models.FeatureBenefit
	if err := h.db.First(&benefit, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return c.JSON(http.StatusNotFound, map[string]interface{}{"error": "Feature benefit not found"})
		}
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to fetch feature benefit"})
	}

	response := FeatureBenefitResponse{
		ID:           benefit.ID,
		FeatureName:  benefit.FeatureName,
		FreeTierText: benefit.FreeTierText,
		ProTierText:  benefit.ProTierText,
		DisplayOrder: benefit.DisplayOrder,
		IsActive:     benefit.IsActive,
		CreatedAt:    benefit.CreatedAt.Format("2006-01-02T15:04:05Z"),
		UpdatedAt:    benefit.UpdatedAt.Format("2006-01-02T15:04:05Z"),
	}

	return c.JSON(http.StatusOK, response)
}

// Create handles POST /api/admin/feature-benefits
func (h *AdminFeatureBenefitHandler) Create(c echo.Context) error {
	var req struct {
		FeatureName  string `json:"feature_name" validate:"required"`
		FreeTierText string `json:"free_tier_text" validate:"required"`
		ProTierText  string `json:"pro_tier_text" validate:"required"`
		DisplayOrder int    `json:"display_order"`
		IsActive     *bool  `json:"is_active"`
	}

	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid request body"})
	}
	if err := c.Validate(&req); err != nil {
		return err
	}

	benefit := models.FeatureBenefit{
		FeatureName:  req.FeatureName,
		FreeTierText: req.FreeTierText,
		ProTierText:  req.ProTierText,
		DisplayOrder: req.DisplayOrder,
		IsActive:     true,
	}

	if req.IsActive != nil {
		benefit.IsActive = *req.IsActive
	}

	if err := h.db.Create(&benefit).Error; err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to create feature benefit"})
	}

	return c.JSON(http.StatusCreated, FeatureBenefitResponse{
		ID:           benefit.ID,
		FeatureName:  benefit.FeatureName,
		FreeTierText: benefit.FreeTierText,
		ProTierText:  benefit.ProTierText,
		DisplayOrder: benefit.DisplayOrder,
		IsActive:     benefit.IsActive,
		CreatedAt:    benefit.CreatedAt.Format("2006-01-02T15:04:05Z"),
		UpdatedAt:    benefit.UpdatedAt.Format("2006-01-02T15:04:05Z"),
	})
}

// Update handles PUT /api/admin/feature-benefits/:id
func (h *AdminFeatureBenefitHandler) Update(c echo.Context) error {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid ID"})
	}

	var benefit models.FeatureBenefit
	if err := h.db.First(&benefit, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return c.JSON(http.StatusNotFound, map[string]interface{}{"error": "Feature benefit not found"})
		}
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to fetch feature benefit"})
	}

	var req struct {
		FeatureName  *string `json:"feature_name"`
		FreeTierText *string `json:"free_tier_text"`
		ProTierText  *string `json:"pro_tier_text"`
		DisplayOrder *int    `json:"display_order"`
		IsActive     *bool   `json:"is_active"`
	}

	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid request body"})
	}

	if req.FeatureName != nil {
		benefit.FeatureName = *req.FeatureName
	}
	if req.FreeTierText != nil {
		benefit.FreeTierText = *req.FreeTierText
	}
	if req.ProTierText != nil {
		benefit.ProTierText = *req.ProTierText
	}
	if req.DisplayOrder != nil {
		benefit.DisplayOrder = *req.DisplayOrder
	}
	if req.IsActive != nil {
		benefit.IsActive = *req.IsActive
	}

	if err := h.db.Save(&benefit).Error; err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to update feature benefit"})
	}

	return c.JSON(http.StatusOK, FeatureBenefitResponse{
		ID:           benefit.ID,
		FeatureName:  benefit.FeatureName,
		FreeTierText: benefit.FreeTierText,
		ProTierText:  benefit.ProTierText,
		DisplayOrder: benefit.DisplayOrder,
		IsActive:     benefit.IsActive,
		CreatedAt:    benefit.CreatedAt.Format("2006-01-02T15:04:05Z"),
		UpdatedAt:    benefit.UpdatedAt.Format("2006-01-02T15:04:05Z"),
	})
}

// Delete handles DELETE /api/admin/feature-benefits/:id
func (h *AdminFeatureBenefitHandler) Delete(c echo.Context) error {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid ID"})
	}

	result := h.db.Delete(&models.FeatureBenefit{}, id)
	if result.Error != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to delete feature benefit"})
	}

	if result.RowsAffected == 0 {
		return c.JSON(http.StatusNotFound, map[string]interface{}{"error": "Feature benefit not found"})
	}

	return c.JSON(http.StatusOK, map[string]interface{}{"message": "Feature benefit deleted successfully"})
}
