package handlers

import (
	"net/http"
	"strconv"

	"github.com/breakpilot/ai-compliance-sdk/internal/academy"
	"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"
)

// ============================================================================
// Deadline / Escalation Endpoints
// ============================================================================

// GetDeadlines returns upcoming deadlines
// GET /sdk/v1/training/deadlines
func (h *TrainingHandlers) GetDeadlines(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

	limit := 20
	if v := c.Query("limit"); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			limit = n
		}
	}

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

	c.JSON(http.StatusOK, training.DeadlineListResponse{
		Deadlines: deadlines,
		Total:     len(deadlines),
	})
}

// GetOverdueDeadlines returns overdue assignments
// GET /sdk/v1/training/deadlines/overdue
func (h *TrainingHandlers) GetOverdueDeadlines(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

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

	c.JSON(http.StatusOK, training.DeadlineListResponse{
		Deadlines: deadlines,
		Total:     len(deadlines),
	})
}

// CheckEscalation runs the escalation check
// POST /sdk/v1/training/escalation/check
func (h *TrainingHandlers) CheckEscalation(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

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

	overdueAll, _ := h.store.ListOverdueAssignments(c.Request.Context(), tenantID)

	c.JSON(http.StatusOK, training.EscalationResponse{
		Results:      results,
		TotalChecked: len(overdueAll),
		Escalated:    len(results),
	})
}

// ============================================================================
// Audit / Stats Endpoints
// ============================================================================

// GetAuditLog returns the training audit trail
// GET /sdk/v1/training/audit-log
func (h *TrainingHandlers) GetAuditLog(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

	filters := &training.AuditLogFilters{
		Limit:  50,
		Offset: 0,
	}

	if v := c.Query("action"); v != "" {
		filters.Action = training.AuditAction(v)
	}
	if v := c.Query("entity_type"); v != "" {
		filters.EntityType = training.AuditEntityType(v)
	}
	if v := c.Query("limit"); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			filters.Limit = n
		}
	}
	if v := c.Query("offset"); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			filters.Offset = n
		}
	}

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

	c.JSON(http.StatusOK, training.AuditLogResponse{
		Entries: entries,
		Total:   total,
	})
}

// GetStats returns training dashboard statistics
// GET /sdk/v1/training/stats
func (h *TrainingHandlers) GetStats(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

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

	c.JSON(http.StatusOK, stats)
}

// VerifyCertificate verifies a certificate
// GET /sdk/v1/training/certificates/:id/verify
func (h *TrainingHandlers) VerifyCertificate(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid certificate ID"})
		return
	}

	valid, assignment, err := training.VerifyCertificate(c.Request.Context(), h.store, id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "certificate not found"})
		return
	}

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

// ============================================================================
// Certificate Endpoints
// ============================================================================

// GenerateCertificate generates a certificate for a completed assignment
// POST /sdk/v1/training/certificates/generate/:assignmentId
func (h *TrainingHandlers) GenerateCertificate(c *gin.Context) {
	assignmentID, err := uuid.Parse(c.Param("assignmentId"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid assignment ID"})
		return
	}
	tenantID := rbac.GetTenantID(c)

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

	if assignment.Status != training.AssignmentStatusCompleted {
		c.JSON(http.StatusBadRequest, gin.H{"error": "assignment is not completed"})
		return
	}
	if assignment.QuizPassed == nil || !*assignment.QuizPassed {
		c.JSON(http.StatusBadRequest, gin.H{"error": "quiz has not been passed"})
		return
	}

	// Generate certificate ID
	certID := uuid.New()
	if err := h.store.SetCertificateID(c.Request.Context(), assignmentID, certID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Audit log
	userID := rbac.GetUserID(c)
	h.store.LogAction(c.Request.Context(), &training.AuditLogEntry{
		TenantID:   tenantID,
		UserID:     &userID,
		Action:     training.AuditActionCertificateIssued,
		EntityType: training.AuditEntityCertificate,
		EntityID:   &certID,
		Details: map[string]interface{}{
			"assignment_id": assignmentID.String(),
			"user_name":     assignment.UserName,
			"module_title":  assignment.ModuleTitle,
		},
	})

	// Reload assignment with certificate_id
	assignment, _ = h.store.GetAssignment(c.Request.Context(), assignmentID)

	c.JSON(http.StatusOK, gin.H{
		"certificate_id": certID,
		"assignment":     assignment,
	})
}

// DownloadCertificatePDF generates and returns a PDF certificate
// GET /sdk/v1/training/certificates/:id/pdf
func (h *TrainingHandlers) DownloadCertificatePDF(c *gin.Context) {
	certID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid certificate ID"})
		return
	}

	assignment, err := h.store.GetAssignmentByCertificateID(c.Request.Context(), certID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if assignment == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "certificate not found"})
		return
	}

	// Get module for title
	module, _ := h.store.GetModule(c.Request.Context(), assignment.ModuleID)
	courseName := assignment.ModuleTitle
	if module != nil {
		courseName = module.Title
	}

	score := 0
	if assignment.QuizScore != nil {
		score = int(*assignment.QuizScore)
	}

	issuedAt := assignment.UpdatedAt
	if assignment.CompletedAt != nil {
		issuedAt = *assignment.CompletedAt
	}

	// Use academy PDF generator
	pdfBytes, err := academy.GenerateCertificatePDF(academy.CertificateData{
		CertificateID: certID.String(),
		UserName:      assignment.UserName,
		CourseName:    courseName,
		Score:         score,
		IssuedAt:      issuedAt,
		ValidUntil:    issuedAt.AddDate(1, 0, 0),
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "PDF generation failed: " + err.Error()})
		return
	}

	c.Header("Content-Disposition", "attachment; filename=zertifikat-"+certID.String()[:8]+".pdf")
	c.Data(http.StatusOK, "application/pdf", pdfBytes)
}

// ListCertificates returns all certificates for a tenant
// GET /sdk/v1/training/certificates
func (h *TrainingHandlers) ListCertificates(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

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

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