package handlers

import (
	"net/http"

	"github.com/breakpilot/ai-compliance-sdk/internal/rbac"
	"github.com/breakpilot/ai-compliance-sdk/internal/training"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// ============================================================================
// Training Block Endpoints (Controls → Schulungsmodule)
// ============================================================================

// ListBlockConfigs returns all block configs for the tenant
// GET /sdk/v1/training/blocks
func (h *TrainingHandlers) ListBlockConfigs(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

	configs, err := h.store.ListBlockConfigs(c.Request.Context(), tenantID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"blocks": configs,
		"total":  len(configs),
	})
}

// CreateBlockConfig creates a new block configuration
// POST /sdk/v1/training/blocks
func (h *TrainingHandlers) CreateBlockConfig(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

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

	config := &training.TrainingBlockConfig{
		TenantID:             tenantID,
		Name:                 req.Name,
		Description:          req.Description,
		DomainFilter:         req.DomainFilter,
		CategoryFilter:       req.CategoryFilter,
		SeverityFilter:       req.SeverityFilter,
		TargetAudienceFilter: req.TargetAudienceFilter,
		RegulationArea:       req.RegulationArea,
		ModuleCodePrefix:     req.ModuleCodePrefix,
		FrequencyType:        req.FrequencyType,
		DurationMinutes:      req.DurationMinutes,
		PassThreshold:        req.PassThreshold,
		MaxControlsPerModule: req.MaxControlsPerModule,
	}

	if config.FrequencyType == "" {
		config.FrequencyType = training.FrequencyAnnual
	}
	if config.DurationMinutes == 0 {
		config.DurationMinutes = 45
	}
	if config.PassThreshold == 0 {
		config.PassThreshold = 70
	}
	if config.MaxControlsPerModule == 0 {
		config.MaxControlsPerModule = 20
	}

	if err := h.store.CreateBlockConfig(c.Request.Context(), config); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, config)
}

// GetBlockConfig returns a single block config
// GET /sdk/v1/training/blocks/:id
func (h *TrainingHandlers) GetBlockConfig(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid block config ID"})
		return
	}

	config, err := h.store.GetBlockConfig(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if config == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "block config not found"})
		return
	}

	c.JSON(http.StatusOK, config)
}

// UpdateBlockConfig updates a block config
// PUT /sdk/v1/training/blocks/:id
func (h *TrainingHandlers) UpdateBlockConfig(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid block config ID"})
		return
	}

	config, err := h.store.GetBlockConfig(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if config == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "block config not found"})
		return
	}

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

	if req.Name != nil {
		config.Name = *req.Name
	}
	if req.Description != nil {
		config.Description = *req.Description
	}
	if req.DomainFilter != nil {
		config.DomainFilter = *req.DomainFilter
	}
	if req.CategoryFilter != nil {
		config.CategoryFilter = *req.CategoryFilter
	}
	if req.SeverityFilter != nil {
		config.SeverityFilter = *req.SeverityFilter
	}
	if req.TargetAudienceFilter != nil {
		config.TargetAudienceFilter = *req.TargetAudienceFilter
	}
	if req.MaxControlsPerModule != nil {
		config.MaxControlsPerModule = *req.MaxControlsPerModule
	}
	if req.DurationMinutes != nil {
		config.DurationMinutes = *req.DurationMinutes
	}
	if req.PassThreshold != nil {
		config.PassThreshold = *req.PassThreshold
	}
	if req.IsActive != nil {
		config.IsActive = *req.IsActive
	}

	if err := h.store.UpdateBlockConfig(c.Request.Context(), config); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, config)
}

// DeleteBlockConfig deletes a block config
// DELETE /sdk/v1/training/blocks/:id
func (h *TrainingHandlers) DeleteBlockConfig(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid block config ID"})
		return
	}

	if err := h.store.DeleteBlockConfig(c.Request.Context(), id); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"status": "deleted"})
}

// PreviewBlock performs a dry run showing matching controls and proposed roles
// POST /sdk/v1/training/blocks/:id/preview
func (h *TrainingHandlers) PreviewBlock(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid block config ID"})
		return
	}

	preview, err := h.blockGenerator.Preview(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, preview)
}

// GenerateBlock runs the full generation pipeline
// POST /sdk/v1/training/blocks/:id/generate
func (h *TrainingHandlers) GenerateBlock(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid block config ID"})
		return
	}

	var req training.GenerateBlockRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		// Defaults are fine
		req.Language = "de"
		req.AutoMatrix = true
	}

	result, err := h.blockGenerator.Generate(c.Request.Context(), id, req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, result)
}

// GetBlockControls returns control links for a block config
// GET /sdk/v1/training/blocks/:id/controls
func (h *TrainingHandlers) GetBlockControls(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid block config ID"})
		return
	}

	links, err := h.store.GetControlLinksForBlock(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"controls": links,
		"total":    len(links),
	})
}

// ListCanonicalControls returns filtered canonical controls for browsing
// GET /sdk/v1/training/canonical/controls
func (h *TrainingHandlers) ListCanonicalControls(c *gin.Context) {
	domain := c.Query("domain")
	category := c.Query("category")
	severity := c.Query("severity")
	targetAudience := c.Query("target_audience")

	controls, err := h.store.QueryCanonicalControls(c.Request.Context(),
		domain, category, severity, targetAudience,
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"controls": controls,
		"total":    len(controls),
	})
}

// GetCanonicalMeta returns aggregated metadata about canonical controls
// GET /sdk/v1/training/canonical/meta
func (h *TrainingHandlers) GetCanonicalMeta(c *gin.Context) {
	meta, err := h.store.GetCanonicalControlMeta(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, meta)
}
