package handlers

import (
	"net/http"
	"time"

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

// EmailTemplateHandler handles email template operations
type EmailTemplateHandler struct {
	service *services.EmailTemplateService
}

// NewEmailTemplateHandler creates a new email template handler
func NewEmailTemplateHandler(service *services.EmailTemplateService) *EmailTemplateHandler {
	return &EmailTemplateHandler{service: service}
}

// GetAllTemplateTypes returns all available email template types with their variables
// GET /api/v1/admin/email-templates/types
func (h *EmailTemplateHandler) GetAllTemplateTypes(c *gin.Context) {
	types := h.service.GetAllTemplateTypes()
	c.JSON(http.StatusOK, gin.H{"types": types})
}

// GetAllTemplates returns all email templates with their latest published versions
// GET /api/v1/admin/email-templates
func (h *EmailTemplateHandler) GetAllTemplates(c *gin.Context) {
	templates, err := h.service.GetAllTemplates(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"templates": templates})
}

// GetTemplate returns a single template by ID
// GET /api/v1/admin/email-templates/:id
func (h *EmailTemplateHandler) GetTemplate(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid template ID"})
		return
	}

	template, err := h.service.GetTemplateByID(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "template not found"})
		return
	}
	c.JSON(http.StatusOK, template)
}

// CreateTemplate creates a new email template type
// POST /api/v1/admin/email-templates
func (h *EmailTemplateHandler) CreateTemplate(c *gin.Context) {
	var req models.CreateEmailTemplateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	template, err := h.service.CreateEmailTemplate(c.Request.Context(), &req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusCreated, template)
}

// GetTemplateVersions returns all versions for a template
// GET /api/v1/admin/email-templates/:id/versions
func (h *EmailTemplateHandler) GetTemplateVersions(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid template ID"})
		return
	}

	versions, err := h.service.GetVersionsByTemplateID(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"versions": versions})
}

// GetVersion returns a single version by ID
// GET /api/v1/admin/email-template-versions/:id
func (h *EmailTemplateHandler) GetVersion(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid version ID"})
		return
	}

	version, err := h.service.GetVersionByID(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "version not found"})
		return
	}
	c.JSON(http.StatusOK, version)
}

// CreateVersion creates a new version of an email template
// POST /api/v1/admin/email-template-versions
func (h *EmailTemplateHandler) CreateVersion(c *gin.Context) {
	var req models.CreateEmailTemplateVersionRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Get user ID from context
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}
	uid, _ := uuid.Parse(userID.(string))

	version, err := h.service.CreateTemplateVersion(c.Request.Context(), &req, uid)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusCreated, version)
}

// UpdateVersion updates a version
// PUT /api/v1/admin/email-template-versions/:id
func (h *EmailTemplateHandler) UpdateVersion(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid version ID"})
		return
	}

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

	if err := h.service.UpdateVersion(c.Request.Context(), id, &req); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "version updated"})
}

// SubmitForReview submits a version for review
// POST /api/v1/admin/email-template-versions/:id/submit
func (h *EmailTemplateHandler) SubmitForReview(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid version ID"})
		return
	}

	var req struct {
		Comment *string `json:"comment"`
	}
	c.ShouldBindJSON(&req)

	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}
	uid, _ := uuid.Parse(userID.(string))

	if err := h.service.SubmitForReview(c.Request.Context(), id, uid, req.Comment); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "version submitted for review"})
}

// ApproveVersion approves a version (DSB only)
// POST /api/v1/admin/email-template-versions/:id/approve
func (h *EmailTemplateHandler) ApproveVersion(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid version ID"})
		return
	}

	// Check role
	role, exists := c.Get("user_role")
	if !exists || (role != "data_protection_officer" && role != "admin" && role != "super_admin") {
		c.JSON(http.StatusForbidden, gin.H{"error": "insufficient permissions"})
		return
	}

	var req struct {
		Comment            *string `json:"comment"`
		ScheduledPublishAt *string `json:"scheduled_publish_at"`
	}
	c.ShouldBindJSON(&req)

	userID, _ := c.Get("user_id")
	uid, _ := uuid.Parse(userID.(string))

	var scheduledAt *time.Time
	if req.ScheduledPublishAt != nil {
		t, err := time.Parse(time.RFC3339, *req.ScheduledPublishAt)
		if err == nil {
			scheduledAt = &t
		}
	}

	if err := h.service.ApproveVersion(c.Request.Context(), id, uid, req.Comment, scheduledAt); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "version approved"})
}

// RejectVersion rejects a version
// POST /api/v1/admin/email-template-versions/:id/reject
func (h *EmailTemplateHandler) RejectVersion(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid version ID"})
		return
	}

	role, exists := c.Get("user_role")
	if !exists || (role != "data_protection_officer" && role != "admin" && role != "super_admin") {
		c.JSON(http.StatusForbidden, gin.H{"error": "insufficient permissions"})
		return
	}

	var req struct {
		Comment string `json:"comment" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "comment is required"})
		return
	}

	userID, _ := c.Get("user_id")
	uid, _ := uuid.Parse(userID.(string))

	if err := h.service.RejectVersion(c.Request.Context(), id, uid, req.Comment); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "version rejected"})
}
