package controllers

import (
	"encoding/json"
	"net/http"
	"time"

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

type MyUIbrixController struct {
	DB *gorm.DB
}

// PageElementConfigRequest represents element configuration
type PageElementConfigRequest struct {
	PageType     string                   `json:"page_type" binding:"required"`
	ElementName  string                   `json:"element_name" binding:"required"`
	Variant      string                   `json:"variant"`
	Visible      bool                     `json:"visible"`
	DisplayOrder int                      `json:"display_order"`
	CustomStyles map[string]interface{}   `json:"custom_styles"`
}

// ValidateElementConfig validates and optimizes element configuration
func (ctrl *MyUIbrixController) ValidateElementConfig(c *gin.Context) {
	var req PageElementConfigRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Validate element name (alphanumeric, underscore, hyphen only)
	if !isValidElementName(req.ElementName) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid element name"})
		return
	}

	// Optimize custom styles by removing redundant properties
	optimizedStyles := optimizeStyles(req.CustomStyles)

	c.JSON(http.StatusOK, gin.H{
		"valid": true,
		"optimized_styles": optimizedStyles,
		"suggestions": generateStyleSuggestions(req.ElementName, optimizedStyles),
	})
}

// GetElementPreview generates server-side preview data
func (ctrl *MyUIbrixController) GetElementPreview(c *gin.Context) {
	elementName := c.Query("element")
	variant := c.Query("variant")
	viewport := c.Query("viewport") // desktop, tablet, mobile

	if elementName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "element required"})
		return
	}

	// Generate preview metadata
	preview := generatePreviewMetadata(elementName, variant, viewport)
	
	c.JSON(http.StatusOK, preview)
}

// BatchValidateConfigs validates multiple configs at once
func (ctrl *MyUIbrixController) BatchValidateConfigs(c *gin.Context) {
	var configs []PageElementConfigRequest
	if err := c.ShouldBindJSON(&configs); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	results := make([]map[string]interface{}, 0, len(configs))
	
	for _, config := range configs {
		if !isValidElementName(config.ElementName) {
			results = append(results, map[string]interface{}{
				"element_name": config.ElementName,
				"valid": false,
				"error": "Invalid element name",
			})
			continue
		}

		optimizedStyles := optimizeStyles(config.CustomStyles)
		results = append(results, map[string]interface{}{
			"element_name": config.ElementName,
			"valid": true,
			"optimized_styles": optimizedStyles,
			"display_order": config.DisplayOrder,
		})
	}

	c.JSON(http.StatusOK, gin.H{
		"results": results,
		"timestamp": time.Now().Unix(),
	})
}

// OptimizePageLayout analyzes and optimizes page element layout
func (ctrl *MyUIbrixController) OptimizePageLayout(c *gin.Context) {
	pageType := c.Query("page_type")
	if pageType == "" {
		pageType = "homepage"
	}

	// Load current configurations from database
	var configs []map[string]interface{}
	
	query := `
		SELECT element_name, variant, visible, display_order, custom_styles 
		FROM page_element_configs 
		WHERE page_type = ? 
		ORDER BY display_order ASC
	`
	
	rows, err := ctrl.DB.Raw(query, pageType).Rows()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load configs"})
		return
	}
	defer rows.Close()

	for rows.Next() {
		var elementName, variant string
		var visible bool
		var displayOrder int
		var customStylesJSON []byte
		
		if err := rows.Scan(&elementName, &variant, &visible, &displayOrder, &customStylesJSON); err != nil {
			continue
		}

		var customStyles map[string]interface{}
		if len(customStylesJSON) > 0 {
			json.Unmarshal(customStylesJSON, &customStyles)
		}

		configs = append(configs, map[string]interface{}{
			"element_name": elementName,
			"variant": variant,
			"visible": visible,
			"display_order": displayOrder,
			"custom_styles": customStyles,
		})
	}

	// Generate optimization suggestions
	suggestions := generateLayoutSuggestions(configs)

	c.JSON(http.StatusOK, gin.H{
		"current_layout": configs,
		"suggestions": suggestions,
		"performance_score": calculatePerformanceScore(configs),
	})
}

// Helper functions

func isValidElementName(name string) bool {
	if name == "" || len(name) > 100 {
		return false
	}
	for _, r := range name {
		if !((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || 
		     (r >= '0' && r <= '9') || r == '_' || r == '-') {
			return false
		}
	}
	return true
}

func optimizeStyles(styles map[string]interface{}) map[string]interface{} {
	if styles == nil {
		return make(map[string]interface{})
	}

	optimized := make(map[string]interface{})
	
	// Remove redundant or default values
	for key, value := range styles {
		// Skip empty values
		if value == nil || value == "" || value == 0 {
			continue
		}
		
		// Skip defaults
		if isDefaultValue(key, value) {
			continue
		}
		
		optimized[key] = value
	}

	return optimized
}

func isDefaultValue(key string, value interface{}) bool {
	defaults := map[string]interface{}{
		"margin": "0",
		"padding": "0",
		"border": "none",
		"background": "transparent",
		"opacity": 1,
		"display": "block",
	}
	
	if defaultVal, exists := defaults[key]; exists {
		return value == defaultVal
	}
	return false
}

func generateStyleSuggestions(elementName string, styles map[string]interface{}) []string {
	suggestions := []string{}
	
	// Check for performance-heavy properties
	if _, hasBoxShadow := styles["box-shadow"]; hasBoxShadow {
		if _, hasFilter := styles["filter"]; hasFilter {
			suggestions = append(suggestions, "Multiple shadows and filters may impact performance")
		}
	}
	
	// Check for conflicting properties
	if position, ok := styles["position"].(string); ok {
		if position == "fixed" || position == "sticky" {
			suggestions = append(suggestions, "Fixed/sticky positioning may cause layout issues on mobile")
		}
	}
	
	return suggestions
}

func generatePreviewMetadata(elementName, variant, viewport string) map[string]interface{} {
	// Generate viewport-specific metadata
	dimensions := map[string]map[string]int{
		"desktop": {"width": 1920, "height": 1080},
		"tablet":  {"width": 768, "height": 1024},
		"mobile":  {"width": 375, "height": 667},
	}
	
	dim := dimensions["desktop"]
	if d, ok := dimensions[viewport]; ok {
		dim = d
	}
	
	return map[string]interface{}{
		"element_name": elementName,
		"variant": variant,
		"viewport": viewport,
		"dimensions": dim,
		"render_hints": map[string]interface{}{
			"use_gpu_acceleration": true,
			"optimize_images": true,
			"lazy_load": viewport == "mobile",
		},
	}
}

func generateLayoutSuggestions(configs []map[string]interface{}) []string {
	suggestions := []string{}
	
	visibleCount := 0
	for _, config := range configs {
		if visible, ok := config["visible"].(bool); ok && visible {
			visibleCount++
		}
	}
	
	if visibleCount > 15 {
		suggestions = append(suggestions, "Consider hiding some elements to improve page load time")
	}
	
	if visibleCount < 3 {
		suggestions = append(suggestions, "Page may look empty - consider adding more visible elements")
	}
	
	return suggestions
}

func calculatePerformanceScore(configs []map[string]interface{}) int {
	score := 100
	
	// Deduct for too many visible elements
	visibleCount := 0
	for _, config := range configs {
		if visible, ok := config["visible"].(bool); ok && visible {
			visibleCount++
		}
	}
	
	if visibleCount > 15 {
		score -= (visibleCount - 15) * 2
	}
	
	// Deduct for heavy custom styles
	heavyStyleCount := 0
	for _, config := range configs {
		if styles, ok := config["custom_styles"].(map[string]interface{}); ok {
			if len(styles) > 10 {
				heavyStyleCount++
			}
		}
	}
	
	score -= heavyStyleCount * 5
	
	if score < 0 {
		score = 0
	}
	if score > 100 {
		score = 100
	}
	
	return score
}
