package handlers

import (
	"net/http"
	"time"

	"github.com/breakpilot/consent-service/internal/middleware"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// ========================================
// TEMPLATE ENDPOINTS
// ========================================

// AdminGetDSRTemplates returns all DSR templates
func (h *DSRHandler) AdminGetDSRTemplates(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	ctx := c.Request.Context()
	rows, err := h.dsrService.GetPool().Query(ctx, `
		SELECT id, template_type, name, description, request_types, is_active, sort_order, created_at, updated_at
		FROM dsr_templates ORDER BY sort_order, name
	`)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch templates"})
		return
	}
	defer rows.Close()

	var templates []map[string]interface{}
	for rows.Next() {
		var id uuid.UUID
		var templateType, name string
		var description *string
		var requestTypes []byte
		var isActive bool
		var sortOrder int
		var createdAt, updatedAt time.Time

		err := rows.Scan(&id, &templateType, &name, &description, &requestTypes, &isActive, &sortOrder, &createdAt, &updatedAt)
		if err != nil {
			continue
		}

		templates = append(templates, map[string]interface{}{
			"id":            id,
			"template_type": templateType,
			"name":          name,
			"description":   description,
			"request_types": string(requestTypes),
			"is_active":     isActive,
			"sort_order":    sortOrder,
			"created_at":    createdAt,
			"updated_at":    updatedAt,
		})
	}

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

// AdminGetDSRTemplateVersions returns versions for a template
func (h *DSRHandler) AdminGetDSRTemplateVersions(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	templateID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid template ID"})
		return
	}

	ctx := c.Request.Context()
	rows, err := h.dsrService.GetPool().Query(ctx, `
		SELECT id, template_id, version, language, subject, body_html, body_text,
			   status, published_at, created_by, approved_by, approved_at, created_at, updated_at
		FROM dsr_template_versions WHERE template_id = $1 ORDER BY created_at DESC
	`, templateID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch versions"})
		return
	}
	defer rows.Close()

	var versions []map[string]interface{}
	for rows.Next() {
		var id, tempID uuid.UUID
		var version, language, subject, bodyHTML, bodyText, status string
		var publishedAt, approvedAt *time.Time
		var createdBy, approvedBy *uuid.UUID
		var createdAt, updatedAt time.Time

		err := rows.Scan(&id, &tempID, &version, &language, &subject, &bodyHTML, &bodyText,
			&status, &publishedAt, &createdBy, &approvedBy, &approvedAt, &createdAt, &updatedAt)
		if err != nil {
			continue
		}

		versions = append(versions, map[string]interface{}{
			"id":           id,
			"template_id":  tempID,
			"version":      version,
			"language":     language,
			"subject":      subject,
			"body_html":    bodyHTML,
			"body_text":    bodyText,
			"status":       status,
			"published_at": publishedAt,
			"created_by":   createdBy,
			"approved_by":  approvedBy,
			"approved_at":  approvedAt,
			"created_at":   createdAt,
			"updated_at":   updatedAt,
		})
	}

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

// AdminCreateDSRTemplateVersion creates a new template version
func (h *DSRHandler) AdminCreateDSRTemplateVersion(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	templateID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid template ID"})
		return
	}

	userID, _ := middleware.GetUserID(c)

	var req struct {
		Version  string `json:"version" binding:"required"`
		Language string `json:"language"`
		Subject  string `json:"subject" binding:"required"`
		BodyHTML string `json:"body_html" binding:"required"`
		BodyText string `json:"body_text"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	if req.Language == "" {
		req.Language = "de"
	}

	ctx := c.Request.Context()
	var versionID uuid.UUID
	err = h.dsrService.GetPool().QueryRow(ctx, `
		INSERT INTO dsr_template_versions (template_id, version, language, subject, body_html, body_text, created_by)
		VALUES ($1, $2, $3, $4, $5, $6, $7)
		RETURNING id
	`, templateID, req.Version, req.Language, req.Subject, req.BodyHTML, req.BodyText, userID).Scan(&versionID)

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

	c.JSON(http.StatusCreated, gin.H{
		"message": "Version wurde erstellt",
		"id":      versionID,
	})
}

// AdminPublishDSRTemplateVersion publishes a template version
func (h *DSRHandler) AdminPublishDSRTemplateVersion(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	versionID, err := uuid.Parse(c.Param("versionId"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid version ID"})
		return
	}

	userID, _ := middleware.GetUserID(c)

	ctx := c.Request.Context()
	_, err = h.dsrService.GetPool().Exec(ctx, `
		UPDATE dsr_template_versions
		SET status = 'published', published_at = NOW(), approved_by = $1, approved_at = NOW(), updated_at = NOW()
		WHERE id = $2
	`, userID, versionID)

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

	c.JSON(http.StatusOK, gin.H{"message": "Version wurde veröffentlicht"})
}

// AdminGetPublishedDSRTemplates returns all published templates for selection
func (h *DSRHandler) AdminGetPublishedDSRTemplates(c *gin.Context) {
	if !middleware.IsAdmin(c) && !middleware.IsDSB(c) {
		c.JSON(http.StatusForbidden, gin.H{"error": "Admin or DSB access required"})
		return
	}

	requestType := c.Query("request_type")
	language := c.DefaultQuery("language", "de")

	ctx := c.Request.Context()
	query := `
		SELECT t.id, t.template_type, t.name, t.description,
			   v.id as version_id, v.version, v.subject, v.body_html, v.body_text
		FROM dsr_templates t
		JOIN dsr_template_versions v ON t.id = v.template_id
		WHERE t.is_active = TRUE AND v.status = 'published' AND v.language = $1
	`
	args := []interface{}{language}

	if requestType != "" {
		query += ` AND t.request_types @> $2::jsonb`
		args = append(args, `["`+requestType+`"]`)
	}

	query += " ORDER BY t.sort_order, t.name"

	rows, err := h.dsrService.GetPool().Query(ctx, query, args...)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch templates"})
		return
	}
	defer rows.Close()

	var templates []map[string]interface{}
	for rows.Next() {
		var templateID, versionID uuid.UUID
		var templateType, name, version, subject, bodyHTML, bodyText string
		var description *string

		err := rows.Scan(&templateID, &templateType, &name, &description, &versionID, &version, &subject, &bodyHTML, &bodyText)
		if err != nil {
			continue
		}

		templates = append(templates, map[string]interface{}{
			"template_id":   templateID,
			"template_type": templateType,
			"name":          name,
			"description":   description,
			"version_id":    versionID,
			"version":       version,
			"subject":       subject,
			"body_html":     bodyHTML,
			"body_text":     bodyText,
		})
	}

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