package handlers

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"net/http"
	"strings"
	"time"

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

// GetSiteConfig gibt die Konfiguration für eine Site zurück
// GET /api/v1/banner/config/:siteId
func (h *Handler) GetSiteConfig(c *gin.Context) {
	siteID := c.Param("siteId")

	// Standard-Kategorien (aus Datenbank oder Default)
	categories := []CategoryConfig{
		{
			ID: "essential",
			Name: map[string]string{
				"de": "Essentiell",
				"en": "Essential",
			},
			Description: map[string]string{
				"de": "Notwendig für die Grundfunktionen der Website.",
				"en": "Required for basic website functionality.",
			},
			Required: true,
			Vendors:  []VendorConfig{},
		},
		{
			ID: "functional",
			Name: map[string]string{
				"de": "Funktional",
				"en": "Functional",
			},
			Description: map[string]string{
				"de": "Ermöglicht Personalisierung und Komfortfunktionen.",
				"en": "Enables personalization and comfort features.",
			},
			Required: false,
			Vendors:  []VendorConfig{},
		},
		{
			ID: "analytics",
			Name: map[string]string{
				"de": "Statistik",
				"en": "Analytics",
			},
			Description: map[string]string{
				"de": "Hilft uns, die Website zu verbessern.",
				"en": "Helps us improve the website.",
			},
			Required: false,
			Vendors:  []VendorConfig{},
		},
		{
			ID: "marketing",
			Name: map[string]string{
				"de": "Marketing",
				"en": "Marketing",
			},
			Description: map[string]string{
				"de": "Ermöglicht personalisierte Werbung.",
				"en": "Enables personalized advertising.",
			},
			Required: false,
			Vendors:  []VendorConfig{},
		},
		{
			ID: "social",
			Name: map[string]string{
				"de": "Soziale Medien",
				"en": "Social Media",
			},
			Description: map[string]string{
				"de": "Ermöglicht Inhalte von sozialen Netzwerken.",
				"en": "Enables content from social networks.",
			},
			Required: false,
			Vendors:  []VendorConfig{},
		},
	}

	config := SiteConfig{
		SiteID:     siteID,
		SiteName:   "BreakPilot",
		Categories: categories,
		UI: UIConfig{
			Theme:    "auto",
			Position: "bottom",
		},
		Legal: LegalConfig{
			PrivacyPolicyURL: "/datenschutz",
			ImprintURL:       "/impressum",
		},
	}

	c.JSON(http.StatusOK, config)
}

// ExportBannerConsent exportiert alle Consent-Daten eines Nutzers (DSGVO Art. 20)
// GET /api/v1/banner/consent/export?userId=xxx
func (h *Handler) ExportBannerConsent(c *gin.Context) {
	userID := c.Query("userId")

	if userID == "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"error":   "missing_user_id",
			"message": "userId parameter is required",
		})
		return
	}

	ctx := context.Background()

	rows, err := h.db.Pool.Query(ctx, `
		SELECT id, site_id, device_fingerprint, categories, vendors,
			   version, created_at, updated_at, revoked_at
		FROM banner_consents
		WHERE user_id = $1
		ORDER BY created_at DESC
	`, userID)

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error":   "export_failed",
			"message": "Failed to export consent data",
		})
		return
	}
	defer rows.Close()

	var consents []map[string]interface{}
	for rows.Next() {
		var id, siteID, deviceFingerprint, version string
		var categoriesJSON, vendorsJSON []byte
		var createdAt, updatedAt time.Time
		var revokedAt *time.Time

		rows.Scan(&id, &siteID, &deviceFingerprint, &categoriesJSON, &vendorsJSON,
			&version, &createdAt, &updatedAt, &revokedAt)

		var categories, vendors map[string]bool
		json.Unmarshal(categoriesJSON, &categories)
		json.Unmarshal(vendorsJSON, &vendors)

		consent := map[string]interface{}{
			"consentId": id,
			"siteId":    siteID,
			"consent": map[string]interface{}{
				"categories": categories,
				"vendors":    vendors,
			},
			"createdAt": createdAt.UTC().Format(time.RFC3339),
			"revokedAt": nil,
		}

		if revokedAt != nil {
			consent["revokedAt"] = revokedAt.UTC().Format(time.RFC3339)
		}

		consents = append(consents, consent)
	}

	c.JSON(http.StatusOK, gin.H{
		"userId":     userID,
		"exportedAt": time.Now().UTC().Format(time.RFC3339),
		"consents":   consents,
	})
}

// GetBannerStats gibt anonymisierte Statistiken zurück (Admin)
// GET /api/v1/banner/admin/stats/:siteId
func (h *Handler) GetBannerStats(c *gin.Context) {
	siteID := c.Param("siteId")

	ctx := context.Background()

	// Gesamtanzahl Consents
	var totalConsents int
	h.db.Pool.QueryRow(ctx, `
		SELECT COUNT(*) FROM banner_consents
		WHERE site_id = $1 AND revoked_at IS NULL
	`, siteID).Scan(&totalConsents)

	// Consent-Rate pro Kategorie
	categoryStats := make(map[string]map[string]interface{})

	rows, _ := h.db.Pool.Query(ctx, `
		SELECT
			key as category,
			COUNT(*) FILTER (WHERE value::text = 'true') as accepted,
			COUNT(*) as total
		FROM banner_consents,
			 jsonb_each(categories::jsonb)
		WHERE site_id = $1 AND revoked_at IS NULL
		GROUP BY key
	`, siteID)

	if rows != nil {
		defer rows.Close()
		for rows.Next() {
			var category string
			var accepted, total int
			rows.Scan(&category, &accepted, &total)

			rate := float64(0)
			if total > 0 {
				rate = float64(accepted) / float64(total)
			}

			categoryStats[category] = map[string]interface{}{
				"accepted": accepted,
				"rate":     rate,
			}
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"siteId": siteID,
		"period": gin.H{
			"from": time.Now().AddDate(0, -1, 0).Format("2006-01-02"),
			"to":   time.Now().Format("2006-01-02"),
		},
		"totalConsents":     totalConsents,
		"consentByCategory": categoryStats,
	})
}

// ========================================
// Helper Functions
// ========================================

// anonymizeIP anonymisiert eine IP-Adresse (DSGVO-konform)
func anonymizeIP(ip string) string {
	// IPv4: Letztes Oktett auf 0
	parts := strings.Split(ip, ".")
	if len(parts) == 4 {
		parts[3] = "0"
		anonymized := strings.Join(parts, ".")
		hash := sha256.Sum256([]byte(anonymized))
		return hex.EncodeToString(hash[:])[:16]
	}

	// IPv6: Hash
	hash := sha256.Sum256([]byte(ip))
	return hex.EncodeToString(hash[:])[:16]
}

// logBannerConsentAudit schreibt einen Audit-Log-Eintrag
func (h *Handler) logBannerConsentAudit(ctx context.Context, consentID, action string, req interface{}, ipHash string) {
	details, _ := json.Marshal(req)

	h.db.Pool.Exec(ctx, `
		INSERT INTO banner_consent_audit_log (
			id, consent_id, action, details, ip_hash, created_at
		) VALUES ($1, $2, $3, $4, $5, NOW())
	`, uuid.New().String(), consentID, action, string(details), ipHash)
}
