package controllers

import (
	"fotbal-club/internal/models"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type PageElementConfigController struct {
	DB *gorm.DB
}

func NewPageElementConfigController(db *gorm.DB) *PageElementConfigController {
	return &PageElementConfigController{DB: db}
}

// GetPageElementConfigs returns all element configurations for a specific page
// @Summary Get page element configurations
// @Description Returns all element configurations for a specific page type
// @Tags page-elements
// @Produce json
// @Param page_type query string true "Page type (e.g., homepage, about)"
// @Success 200 {array} models.PageElementConfig
// @Router /api/v1/page-elements [get]
func (pc *PageElementConfigController) GetPageElementConfigs(c *gin.Context) {
	pageType := c.Query("page_type")
	if pageType == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "page_type is required"})
		return
	}

	var configs []models.PageElementConfig
	if err := pc.DB.Where("page_type = ?", pageType).Find(&configs).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch configurations"})
		return
	}

	c.JSON(http.StatusOK, configs)
}

// GetAllPageElementConfigs returns all element configurations (admin)
// @Summary Get all page element configurations
// @Description Returns all element configurations for admin management
// @Tags page-elements
// @Produce json
// @Security BearerAuth
// @Success 200 {array} models.PageElementConfig
// @Router /api/v1/admin/page-elements [get]
func (pc *PageElementConfigController) GetAllPageElementConfigs(c *gin.Context) {
	var configs []models.PageElementConfig
	if err := pc.DB.Order("page_type ASC, element_name ASC").Find(&configs).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch configurations"})
		return
	}

	c.JSON(http.StatusOK, configs)
}

// CreateOrUpdatePageElementConfig creates or updates an element configuration
// @Summary Create or update page element configuration
// @Description Creates or updates a page element configuration
// @Tags page-elements
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param config body models.PageElementConfig true "Element configuration data"
// @Success 200 {object} models.PageElementConfig
// @Router /api/v1/admin/page-elements [post]
func (pc *PageElementConfigController) CreateOrUpdatePageElementConfig(c *gin.Context) {
	var input models.PageElementConfig

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

	// Check if config already exists
	var existing models.PageElementConfig
	result := pc.DB.Where("page_type = ? AND element_name = ?", input.PageType, input.ElementName).First(&existing)

	if result.Error == nil {
		// Update existing
		existing.Variant = input.Variant
		existing.Settings = input.Settings
		if err := pc.DB.Save(&existing).Error; err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update configuration"})
			return
		}
		c.JSON(http.StatusOK, existing)
	} else {
		// Create new
		if err := pc.DB.Create(&input).Error; err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create configuration"})
			return
		}
		c.JSON(http.StatusCreated, input)
	}
}

// UpdatePageElementConfig updates an existing element configuration
// @Summary Update page element configuration
// @Description Updates an existing page element configuration
// @Tags page-elements
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "Configuration ID"
// @Param config body models.PageElementConfig true "Updated configuration data"
// @Success 200 {object} models.PageElementConfig
// @Router /api/v1/admin/page-elements/{id} [put]
func (pc *PageElementConfigController) UpdatePageElementConfig(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
		return
	}

	var config models.PageElementConfig
	if err := pc.DB.First(&config, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Configuration not found"})
		return
	}

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

	config.PageType = updates.PageType
	config.ElementName = updates.ElementName
	config.Variant = updates.Variant
	config.Settings = updates.Settings

	if err := pc.DB.Save(&config).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update configuration"})
		return
	}

	c.JSON(http.StatusOK, config)
}

// DeletePageElementConfig deletes an element configuration
// @Summary Delete page element configuration
// @Description Deletes a page element configuration
// @Tags page-elements
// @Produce json
// @Security BearerAuth
// @Param id path int true "Configuration ID"
// @Success 200 {object} map[string]string
// @Router /api/v1/admin/page-elements/{id} [delete]
func (pc *PageElementConfigController) DeletePageElementConfig(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
		return
	}

	if err := pc.DB.Delete(&models.PageElementConfig{}, id).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete configuration"})
		return
	}

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

// BatchUpdatePageElementConfigs updates multiple element configurations at once
// @Summary Batch update page element configurations
// @Description Updates multiple element configurations in one request
// @Tags page-elements
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param configs body []models.PageElementConfig true "Array of configurations"
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/admin/page-elements/batch [post]
func (pc *PageElementConfigController) BatchUpdatePageElementConfigs(c *gin.Context) {
	var configs []models.PageElementConfig
	if err := c.ShouldBindJSON(&configs); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	updated := 0
	created := 0

	err := pc.DB.Transaction(func(tx *gorm.DB) error {
		for _, cfg := range configs {
			var existing models.PageElementConfig
			result := tx.Where("page_type = ? AND element_name = ?", cfg.PageType, cfg.ElementName).First(&existing)

			if result.Error == nil {
				// Update
				existing.Variant = cfg.Variant
				existing.Visible = cfg.Visible
				existing.DisplayOrder = cfg.DisplayOrder
				existing.Settings = cfg.Settings
				if err := tx.Save(&existing).Error; err != nil {
					return err
				}
				updated++
			} else {
				// Create
				if err := tx.Create(&cfg).Error; err != nil {
					return err
				}
				created++
			}
		}
		return nil
	})

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to batch update configurations"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "Batch update successful",
		"updated": updated,
		"created": created,
	})
}
