package api

import (
	"fmt"
	"net/http"
	"time"

	"github.com/breakpilot/ai-compliance-sdk/internal/academy"
	"github.com/breakpilot/ai-compliance-sdk/internal/db"
	"github.com/breakpilot/ai-compliance-sdk/internal/llm"
	"github.com/breakpilot/ai-compliance-sdk/internal/rag"
	"github.com/gin-gonic/gin"
)

// AcademyHandler handles all Academy-related HTTP requests
type AcademyHandler struct {
	dbPool       *db.Pool
	llmService   *llm.Service
	ragService   *rag.Service
	academyStore *db.AcademyMemStore
}

// NewAcademyHandler creates a new Academy handler
func NewAcademyHandler(dbPool *db.Pool, llmService *llm.Service, ragService *rag.Service) *AcademyHandler {
	return &AcademyHandler{
		dbPool:       dbPool,
		llmService:   llmService,
		ragService:   ragService,
		academyStore: db.NewAcademyMemStore(),
	}
}

func (h *AcademyHandler) getTenantID(c *gin.Context) string {
	tid := c.GetHeader("X-Tenant-ID")
	if tid == "" {
		tid = c.Query("tenantId")
	}
	if tid == "" {
		tid = "default-tenant"
	}
	return tid
}

// ---------------------------------------------------------------------------
// Course CRUD
// ---------------------------------------------------------------------------

// ListCourses returns all courses for the tenant
func (h *AcademyHandler) ListCourses(c *gin.Context) {
	tenantID := h.getTenantID(c)
	rows := h.academyStore.ListCourses(tenantID)

	courses := make([]AcademyCourse, 0, len(rows))
	for _, row := range rows {
		lessons := h.buildLessonsForCourse(row.ID)
		courses = append(courses, courseRowToResponse(row, lessons))
	}

	SuccessResponse(c, courses)
}

// GetCourse returns a single course with its lessons
func (h *AcademyHandler) GetCourse(c *gin.Context) {
	id := c.Param("id")
	row, err := h.academyStore.GetCourse(id)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Course not found", "COURSE_NOT_FOUND")
		return
	}

	lessons := h.buildLessonsForCourse(row.ID)
	SuccessResponse(c, courseRowToResponse(row, lessons))
}

// CreateCourse creates a new course with optional lessons
func (h *AcademyHandler) CreateCourse(c *gin.Context) {
	var req CreateCourseRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		ErrorResponse(c, http.StatusBadRequest, err.Error(), "INVALID_REQUEST")
		return
	}

	passingScore := req.PassingScore
	if passingScore == 0 {
		passingScore = 70
	}

	roles := req.RequiredForRoles
	if len(roles) == 0 {
		roles = []string{"all"}
	}

	courseRow := h.academyStore.CreateCourse(&db.AcademyCourseRow{
		TenantID:         req.TenantID,
		Title:            req.Title,
		Description:      req.Description,
		Category:         req.Category,
		PassingScore:     passingScore,
		DurationMinutes:  req.DurationMinutes,
		RequiredForRoles: roles,
		Status:           "draft",
	})

	// Create lessons
	for i, lessonReq := range req.Lessons {
		order := lessonReq.Order
		if order == 0 {
			order = i + 1
		}
		lessonRow := h.academyStore.CreateLesson(&db.AcademyLessonRow{
			CourseID:        courseRow.ID,
			Title:           lessonReq.Title,
			Type:            lessonReq.Type,
			ContentMarkdown: lessonReq.ContentMarkdown,
			VideoURL:        lessonReq.VideoURL,
			SortOrder:       order,
			DurationMinutes: lessonReq.DurationMinutes,
		})

		// Create quiz questions for this lesson
		for j, qReq := range lessonReq.QuizQuestions {
			qOrder := qReq.Order
			if qOrder == 0 {
				qOrder = j + 1
			}
			h.academyStore.CreateQuizQuestion(&db.AcademyQuizQuestionRow{
				LessonID:           lessonRow.ID,
				Question:           qReq.Question,
				Options:            qReq.Options,
				CorrectOptionIndex: qReq.CorrectOptionIndex,
				Explanation:        qReq.Explanation,
				SortOrder:          qOrder,
			})
		}
	}

	lessons := h.buildLessonsForCourse(courseRow.ID)
	c.JSON(http.StatusCreated, Response{
		Success: true,
		Data:    courseRowToResponse(courseRow, lessons),
	})
}

// UpdateCourse updates an existing course
func (h *AcademyHandler) UpdateCourse(c *gin.Context) {
	id := c.Param("id")

	var req UpdateCourseRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		ErrorResponse(c, http.StatusBadRequest, err.Error(), "INVALID_REQUEST")
		return
	}

	updates := make(map[string]interface{})
	if req.Title != nil {
		updates["title"] = *req.Title
	}
	if req.Description != nil {
		updates["description"] = *req.Description
	}
	if req.Category != nil {
		updates["category"] = *req.Category
	}
	if req.DurationMinutes != nil {
		updates["durationminutes"] = *req.DurationMinutes
	}
	if req.PassingScore != nil {
		updates["passingscore"] = *req.PassingScore
	}
	if req.RequiredForRoles != nil {
		updates["requiredforroles"] = req.RequiredForRoles
	}

	row, err := h.academyStore.UpdateCourse(id, updates)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Course not found", "COURSE_NOT_FOUND")
		return
	}

	lessons := h.buildLessonsForCourse(row.ID)
	SuccessResponse(c, courseRowToResponse(row, lessons))
}

// DeleteCourse deletes a course and all related data
func (h *AcademyHandler) DeleteCourse(c *gin.Context) {
	id := c.Param("id")

	if err := h.academyStore.DeleteCourse(id); err != nil {
		ErrorResponse(c, http.StatusNotFound, "Course not found", "COURSE_NOT_FOUND")
		return
	}

	SuccessResponse(c, gin.H{
		"courseId":  id,
		"deletedAt": now(),
	})
}

// GetStatistics returns academy statistics for the tenant
func (h *AcademyHandler) GetStatistics(c *gin.Context) {
	tenantID := h.getTenantID(c)
	stats := h.academyStore.GetStatistics(tenantID)

	SuccessResponse(c, AcademyStatistics{
		TotalCourses:     stats.TotalCourses,
		TotalEnrollments: stats.TotalEnrollments,
		CompletionRate:   int(stats.CompletionRate),
		OverdueCount:     stats.OverdueCount,
		ByCategory:       stats.ByCategory,
		ByStatus:         stats.ByStatus,
	})
}

// ---------------------------------------------------------------------------
// Enrollments
// ---------------------------------------------------------------------------

// ListEnrollments returns enrollments filtered by tenant and optionally course
func (h *AcademyHandler) ListEnrollments(c *gin.Context) {
	tenantID := h.getTenantID(c)
	courseID := c.Query("courseId")

	rows := h.academyStore.ListEnrollments(tenantID, courseID)

	enrollments := make([]AcademyEnrollment, 0, len(rows))
	for _, row := range rows {
		enrollments = append(enrollments, enrollmentRowToResponse(row))
	}

	SuccessResponse(c, enrollments)
}

// EnrollUser enrolls a user in a course
func (h *AcademyHandler) EnrollUser(c *gin.Context) {
	var req EnrollUserRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		ErrorResponse(c, http.StatusBadRequest, err.Error(), "INVALID_REQUEST")
		return
	}

	deadline, err := time.Parse(time.RFC3339, req.Deadline)
	if err != nil {
		deadline, err = time.Parse("2006-01-02", req.Deadline)
		if err != nil {
			ErrorResponse(c, http.StatusBadRequest, "Invalid deadline format. Use RFC3339 or YYYY-MM-DD.", "INVALID_DEADLINE")
			return
		}
	}

	row := h.academyStore.CreateEnrollment(&db.AcademyEnrollmentRow{
		TenantID:  req.TenantID,
		CourseID:  req.CourseID,
		UserID:    req.UserID,
		UserName:  req.UserName,
		UserEmail: req.UserEmail,
		Status:    "not_started",
		Progress:  0,
		Deadline:  deadline,
	})

	c.JSON(http.StatusCreated, Response{
		Success: true,
		Data:    enrollmentRowToResponse(row),
	})
}

// UpdateProgress updates the progress of an enrollment
func (h *AcademyHandler) UpdateProgress(c *gin.Context) {
	id := c.Param("id")

	var req UpdateProgressRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		ErrorResponse(c, http.StatusBadRequest, err.Error(), "INVALID_REQUEST")
		return
	}

	enrollment, err := h.academyStore.GetEnrollment(id)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Enrollment not found", "ENROLLMENT_NOT_FOUND")
		return
	}

	updates := map[string]interface{}{
		"progress": req.Progress,
	}

	// Auto-update status based on progress
	if req.Progress >= 100 {
		updates["status"] = "completed"
		t := time.Now()
		updates["completedat"] = &t
	} else if req.Progress > 0 && enrollment.Status == "not_started" {
		updates["status"] = "in_progress"
	}

	row, err := h.academyStore.UpdateEnrollment(id, updates)
	if err != nil {
		ErrorResponse(c, http.StatusInternalServerError, "Failed to update progress", "UPDATE_FAILED")
		return
	}

	// Upsert lesson progress if lessonID provided
	if req.LessonID != "" {
		t := time.Now()
		h.academyStore.UpsertLessonProgress(&db.AcademyLessonProgressRow{
			EnrollmentID: id,
			LessonID:     req.LessonID,
			Completed:    true,
			CompletedAt:  &t,
		})
	}

	SuccessResponse(c, enrollmentRowToResponse(row))
}

// CompleteEnrollment marks an enrollment as completed
func (h *AcademyHandler) CompleteEnrollment(c *gin.Context) {
	id := c.Param("id")

	t := time.Now()
	updates := map[string]interface{}{
		"status":      "completed",
		"progress":    100,
		"completedat": &t,
	}

	row, err := h.academyStore.UpdateEnrollment(id, updates)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Enrollment not found", "ENROLLMENT_NOT_FOUND")
		return
	}

	SuccessResponse(c, enrollmentRowToResponse(row))
}

// ---------------------------------------------------------------------------
// Quiz
// ---------------------------------------------------------------------------

// SubmitQuiz evaluates quiz answers for a lesson
func (h *AcademyHandler) SubmitQuiz(c *gin.Context) {
	lessonID := c.Param("id")

	var req SubmitQuizRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		ErrorResponse(c, http.StatusBadRequest, err.Error(), "INVALID_REQUEST")
		return
	}

	// Get the lesson
	lesson, err := h.academyStore.GetLesson(lessonID)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Lesson not found", "LESSON_NOT_FOUND")
		return
	}

	// Get quiz questions
	questions := h.academyStore.ListQuizQuestions(lessonID)
	if len(questions) == 0 {
		ErrorResponse(c, http.StatusBadRequest, "No quiz questions found for this lesson", "NO_QUIZ_QUESTIONS")
		return
	}

	if len(req.Answers) != len(questions) {
		ErrorResponse(c, http.StatusBadRequest,
			fmt.Sprintf("Expected %d answers, got %d", len(questions), len(req.Answers)),
			"ANSWER_COUNT_MISMATCH")
		return
	}

	// Evaluate answers
	correctCount := 0
	results := make([]QuizQuestionResult, len(questions))
	for i, q := range questions {
		correct := req.Answers[i] == q.CorrectOptionIndex
		if correct {
			correctCount++
		}
		results[i] = QuizQuestionResult{
			QuestionID:  q.ID,
			Correct:     correct,
			Explanation: q.Explanation,
		}
	}

	score := 0
	if len(questions) > 0 {
		score = int(float64(correctCount) / float64(len(questions)) * 100)
	}

	// Determine pass/fail based on course's passing score
	passingScore := 70 // default
	course, err := h.academyStore.GetCourse(lesson.CourseID)
	if err == nil && course.PassingScore > 0 {
		passingScore = course.PassingScore
	}

	SuccessResponse(c, SubmitQuizResponse{
		Score:          score,
		Passed:         score >= passingScore,
		CorrectAnswers: correctCount,
		TotalQuestions: len(questions),
		Results:        results,
	})
}

// ---------------------------------------------------------------------------
// Certificates
// ---------------------------------------------------------------------------

// GenerateCertificateEndpoint generates a certificate for a completed enrollment
func (h *AcademyHandler) GenerateCertificateEndpoint(c *gin.Context) {
	enrollmentID := c.Param("id")

	enrollment, err := h.academyStore.GetEnrollment(enrollmentID)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Enrollment not found", "ENROLLMENT_NOT_FOUND")
		return
	}

	// Check if already has certificate
	if enrollment.CertificateID != "" {
		existing, err := h.academyStore.GetCertificate(enrollment.CertificateID)
		if err == nil {
			SuccessResponse(c, certificateRowToResponse(existing))
			return
		}
	}

	// Get course name
	courseName := "Unbekannter Kurs"
	course, err := h.academyStore.GetCourse(enrollment.CourseID)
	if err == nil {
		courseName = course.Title
	}

	issuedAt := time.Now()
	validUntil := issuedAt.AddDate(1, 0, 0) // 1 year validity

	cert := h.academyStore.CreateCertificate(&db.AcademyCertificateRow{
		TenantID:     enrollment.TenantID,
		EnrollmentID: enrollmentID,
		CourseID:     enrollment.CourseID,
		UserID:       enrollment.UserID,
		UserName:     enrollment.UserName,
		CourseName:   courseName,
		Score:        enrollment.Progress,
		IssuedAt:     issuedAt,
		ValidUntil:   validUntil,
	})

	// Update enrollment with certificate ID
	h.academyStore.UpdateEnrollment(enrollmentID, map[string]interface{}{
		"certificateid": cert.ID,
	})

	c.JSON(http.StatusCreated, Response{
		Success: true,
		Data:    certificateRowToResponse(cert),
	})
}

// GetCertificate returns a certificate by ID
func (h *AcademyHandler) GetCertificate(c *gin.Context) {
	id := c.Param("id")

	cert, err := h.academyStore.GetCertificate(id)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Certificate not found", "CERTIFICATE_NOT_FOUND")
		return
	}

	SuccessResponse(c, certificateRowToResponse(cert))
}

// DownloadCertificatePDF returns the PDF for a certificate
func (h *AcademyHandler) DownloadCertificatePDF(c *gin.Context) {
	id := c.Param("id")

	cert, err := h.academyStore.GetCertificate(id)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Certificate not found", "CERTIFICATE_NOT_FOUND")
		return
	}

	if cert.PdfURL != "" {
		c.Redirect(http.StatusFound, cert.PdfURL)
		return
	}

	// Generate PDF on-the-fly
	pdfBytes, err := academy.GenerateCertificatePDF(academy.CertificateData{
		CertificateID: cert.ID,
		UserName:      cert.UserName,
		CourseName:    cert.CourseName,
		CompanyName:   "",
		Score:         cert.Score,
		IssuedAt:      cert.IssuedAt,
		ValidUntil:    cert.ValidUntil,
	})
	if err != nil {
		ErrorResponse(c, http.StatusInternalServerError, "Failed to generate PDF", "PDF_GENERATION_FAILED")
		return
	}

	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=zertifikat-%s.pdf", cert.ID[:min(8, len(cert.ID))]))
	c.Data(http.StatusOK, "application/pdf", pdfBytes)
}

// ---------------------------------------------------------------------------
// AI Course Generation
// ---------------------------------------------------------------------------

// GenerateCourse generates a course using AI
func (h *AcademyHandler) GenerateCourse(c *gin.Context) {
	var req GenerateCourseRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		ErrorResponse(c, http.StatusBadRequest, err.Error(), "INVALID_REQUEST")
		return
	}

	// Get RAG context if requested
	var ragSources []SearchResult
	if req.UseRAG && h.ragService != nil {
		query := req.RAGQuery
		if query == "" {
			query = req.Topic + " Compliance Schulung"
		}
		results, _ := h.ragService.Search(c.Request.Context(), query, 5, "legal_corpus", "")
		for _, r := range results {
			ragSources = append(ragSources, SearchResult{
				ID:       r.ID,
				Content:  r.Content,
				Source:   r.Source,
				Score:    r.Score,
				Metadata: r.Metadata,
			})
		}
	}

	// Generate course content (mock for now)
	course := h.generateMockCourse(req)

	// Save to store
	courseRow := h.academyStore.CreateCourse(&db.AcademyCourseRow{
		TenantID:         req.TenantID,
		Title:            course.Title,
		Description:      course.Description,
		Category:         req.Category,
		PassingScore:     70,
		DurationMinutes:  course.DurationMinutes,
		RequiredForRoles: []string{"all"},
		Status:           "draft",
	})

	for _, lesson := range course.Lessons {
		lessonRow := h.academyStore.CreateLesson(&db.AcademyLessonRow{
			CourseID:        courseRow.ID,
			Title:           lesson.Title,
			Type:            lesson.Type,
			ContentMarkdown: lesson.ContentMarkdown,
			SortOrder:       lesson.Order,
			DurationMinutes: lesson.DurationMinutes,
		})

		for _, q := range lesson.QuizQuestions {
			h.academyStore.CreateQuizQuestion(&db.AcademyQuizQuestionRow{
				LessonID:           lessonRow.ID,
				Question:           q.Question,
				Options:            q.Options,
				CorrectOptionIndex: q.CorrectOptionIndex,
				Explanation:        q.Explanation,
				SortOrder:          q.Order,
			})
		}
	}

	lessons := h.buildLessonsForCourse(courseRow.ID)
	c.JSON(http.StatusCreated, Response{
		Success: true,
		Data: gin.H{
			"course":     courseRowToResponse(courseRow, lessons),
			"ragSources": ragSources,
			"model":      h.llmService.GetModel(),
		},
	})
}

// RegenerateLesson regenerates a single lesson using AI
func (h *AcademyHandler) RegenerateLesson(c *gin.Context) {
	lessonID := c.Param("id")

	_, err := h.academyStore.GetLesson(lessonID)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Lesson not found", "LESSON_NOT_FOUND")
		return
	}

	// For now, return the existing lesson
	SuccessResponse(c, gin.H{
		"lessonId": lessonID,
		"status":   "regeneration_pending",
		"message":  "AI lesson regeneration will be available in a future version",
	})
}

// ---------------------------------------------------------------------------
// Video Generation
// ---------------------------------------------------------------------------

// GenerateVideos initiates video generation for all lessons in a course
func (h *AcademyHandler) GenerateVideos(c *gin.Context) {
	courseID := c.Param("id")

	_, err := h.academyStore.GetCourse(courseID)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Course not found", "COURSE_NOT_FOUND")
		return
	}

	lessons := h.academyStore.ListLessons(courseID)
	lessonStatuses := make([]LessonVideoStatus, 0, len(lessons))
	for _, l := range lessons {
		if l.Type == "text" || l.Type == "video" {
			lessonStatuses = append(lessonStatuses, LessonVideoStatus{
				LessonID: l.ID,
				Status:   "pending",
			})
		}
	}

	SuccessResponse(c, VideoStatusResponse{
		CourseID: courseID,
		Status:   "pending",
		Lessons:  lessonStatuses,
	})
}

// GetVideoStatus returns the video generation status for a course
func (h *AcademyHandler) GetVideoStatus(c *gin.Context) {
	courseID := c.Param("id")

	_, err := h.academyStore.GetCourse(courseID)
	if err != nil {
		ErrorResponse(c, http.StatusNotFound, "Course not found", "COURSE_NOT_FOUND")
		return
	}

	lessons := h.academyStore.ListLessons(courseID)
	lessonStatuses := make([]LessonVideoStatus, 0, len(lessons))
	for _, l := range lessons {
		status := LessonVideoStatus{
			LessonID: l.ID,
			Status:   "not_started",
			VideoURL: l.VideoURL,
			AudioURL: l.AudioURL,
		}
		if l.VideoURL != "" {
			status.Status = "completed"
		}
		lessonStatuses = append(lessonStatuses, status)
	}

	overallStatus := "not_started"
	hasCompleted := false
	hasPending := false
	for _, s := range lessonStatuses {
		if s.Status == "completed" {
			hasCompleted = true
		} else {
			hasPending = true
		}
	}
	if hasCompleted && !hasPending {
		overallStatus = "completed"
	} else if hasCompleted && hasPending {
		overallStatus = "processing"
	}

	SuccessResponse(c, VideoStatusResponse{
		CourseID: courseID,
		Status:   overallStatus,
		Lessons:  lessonStatuses,
	})
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

func (h *AcademyHandler) buildLessonsForCourse(courseID string) []AcademyLesson {
	lessonRows := h.academyStore.ListLessons(courseID)
	lessons := make([]AcademyLesson, 0, len(lessonRows))
	for _, lr := range lessonRows {
		var questions []AcademyQuizQuestion
		if lr.Type == "quiz" {
			qRows := h.academyStore.ListQuizQuestions(lr.ID)
			questions = make([]AcademyQuizQuestion, 0, len(qRows))
			for _, qr := range qRows {
				questions = append(questions, quizQuestionRowToResponse(qr))
			}
		}
		lessons = append(lessons, lessonRowToResponse(lr, questions))
	}
	return lessons
}

func courseRowToResponse(row *db.AcademyCourseRow, lessons []AcademyLesson) AcademyCourse {
	return AcademyCourse{
		ID:               row.ID,
		TenantID:         row.TenantID,
		Title:            row.Title,
		Description:      row.Description,
		Category:         row.Category,
		PassingScore:     row.PassingScore,
		DurationMinutes:  row.DurationMinutes,
		RequiredForRoles: row.RequiredForRoles,
		Status:           row.Status,
		Lessons:          lessons,
		CreatedAt:        row.CreatedAt.Format(time.RFC3339),
		UpdatedAt:        row.UpdatedAt.Format(time.RFC3339),
	}
}

func lessonRowToResponse(row *db.AcademyLessonRow, questions []AcademyQuizQuestion) AcademyLesson {
	return AcademyLesson{
		ID:              row.ID,
		CourseID:        row.CourseID,
		Title:           row.Title,
		Type:            row.Type,
		ContentMarkdown: row.ContentMarkdown,
		VideoURL:        row.VideoURL,
		AudioURL:        row.AudioURL,
		Order:           row.SortOrder,
		DurationMinutes: row.DurationMinutes,
		QuizQuestions:   questions,
	}
}

func quizQuestionRowToResponse(row *db.AcademyQuizQuestionRow) AcademyQuizQuestion {
	return AcademyQuizQuestion{
		ID:                 row.ID,
		LessonID:           row.LessonID,
		Question:           row.Question,
		Options:            row.Options,
		CorrectOptionIndex: row.CorrectOptionIndex,
		Explanation:        row.Explanation,
		Order:              row.SortOrder,
	}
}

func enrollmentRowToResponse(row *db.AcademyEnrollmentRow) AcademyEnrollment {
	e := AcademyEnrollment{
		ID:            row.ID,
		TenantID:      row.TenantID,
		CourseID:      row.CourseID,
		UserID:        row.UserID,
		UserName:      row.UserName,
		UserEmail:     row.UserEmail,
		Status:        row.Status,
		Progress:      row.Progress,
		StartedAt:     row.StartedAt.Format(time.RFC3339),
		CertificateID: row.CertificateID,
		Deadline:      row.Deadline.Format(time.RFC3339),
		CreatedAt:     row.CreatedAt.Format(time.RFC3339),
		UpdatedAt:     row.UpdatedAt.Format(time.RFC3339),
	}
	if row.CompletedAt != nil {
		e.CompletedAt = row.CompletedAt.Format(time.RFC3339)
	}
	return e
}

func certificateRowToResponse(row *db.AcademyCertificateRow) AcademyCertificate {
	return AcademyCertificate{
		ID:           row.ID,
		TenantID:     row.TenantID,
		EnrollmentID: row.EnrollmentID,
		CourseID:     row.CourseID,
		UserID:       row.UserID,
		UserName:     row.UserName,
		CourseName:   row.CourseName,
		Score:        row.Score,
		IssuedAt:     row.IssuedAt.Format(time.RFC3339),
		ValidUntil:   row.ValidUntil.Format(time.RFC3339),
		PdfURL:       row.PdfURL,
	}
}

// ---------------------------------------------------------------------------
// Mock Course Generator (used when LLM is not available)
// ---------------------------------------------------------------------------

func (h *AcademyHandler) generateMockCourse(req GenerateCourseRequest) AcademyCourse {
	switch req.Category {
	case "dsgvo_basics":
		return h.mockDSGVOCourse(req)
	case "it_security":
		return h.mockITSecurityCourse(req)
	case "ai_literacy":
		return h.mockAILiteracyCourse(req)
	case "whistleblower_protection":
		return h.mockWhistleblowerCourse(req)
	default:
		return h.mockDSGVOCourse(req)
	}
}

func (h *AcademyHandler) mockDSGVOCourse(req GenerateCourseRequest) AcademyCourse {
	return AcademyCourse{
		Title:           "DSGVO-Grundlagen fuer Mitarbeiter",
		Description:     "Umfassende Einfuehrung in die Datenschutz-Grundverordnung. Vermittelt die wichtigsten Grundsaetze des Datenschutzes, Betroffenenrechte und die korrekte Handhabung personenbezogener Daten.",
		DurationMinutes: 90,
		Lessons: []AcademyLesson{
			{
				Title:           "Was ist die DSGVO?",
				Type:            "text",
				Order:           1,
				DurationMinutes: 15,
				ContentMarkdown: "# Was ist die DSGVO?\n\nDie Datenschutz-Grundverordnung (DSGVO) ist eine Verordnung der EU, die seit dem 25. Mai 2018 gilt. Sie schuetzt die Grundrechte natuerlicher Personen bei der Verarbeitung personenbezogener Daten.\n\n## Warum ist die DSGVO wichtig?\n\n- **Einheitlicher Datenschutz** in der gesamten EU\n- **Hohe Bussgelder** bei Verstoessen (bis 20 Mio. EUR oder 4% des Jahresumsatzes)\n- **Staerkung der Betroffenenrechte** (Auskunft, Loeschung, Widerspruch)\n\n## Zentrale Begriffe\n\n- **Personenbezogene Daten**: Alle Informationen, die sich auf eine identifizierte oder identifizierbare Person beziehen\n- **Verantwortlicher**: Die Stelle, die ueber Zweck und Mittel der Verarbeitung entscheidet\n- **Auftragsverarbeiter**: Verarbeitet Daten im Auftrag des Verantwortlichen",
			},
			{
				Title:           "Die 7 Grundsaetze der DSGVO",
				Type:            "text",
				Order:           2,
				DurationMinutes: 20,
				ContentMarkdown: "# Die 7 Grundsaetze der DSGVO (Art. 5)\n\n## 1. Rechtmaessigkeit, Verarbeitung nach Treu und Glauben, Transparenz\nPersonenbezogene Daten muessen auf rechtmaessige Weise verarbeitet werden.\n\n## 2. Zweckbindung\nDaten duerfen nur fuer festgelegte, eindeutige und legitime Zwecke erhoben werden.\n\n## 3. Datenminimierung\nEs duerfen nur Daten erhoben werden, die fuer den Zweck erforderlich sind.\n\n## 4. Richtigkeit\nDaten muessen sachlich richtig und auf dem neuesten Stand sein.\n\n## 5. Speicherbegrenzung\nDaten duerfen nur so lange gespeichert werden, wie es fuer den Zweck erforderlich ist.\n\n## 6. Integritaet und Vertraulichkeit\nDaten muessen vor unbefugtem Zugriff geschuetzt werden.\n\n## 7. Rechenschaftspflicht\nDer Verantwortliche muss die Einhaltung der Grundsaetze nachweisen koennen.",
			},
			{
				Title:           "Betroffenenrechte (Art. 15-22 DSGVO)",
				Type:            "text",
				Order:           3,
				DurationMinutes: 20,
				ContentMarkdown: "# Betroffenenrechte\n\n## Recht auf Auskunft (Art. 15)\nJede Person hat das Recht zu erfahren, ob und welche Daten ueber sie verarbeitet werden.\n\n## Recht auf Berichtigung (Art. 16)\nUnrichtige Daten muessen berichtigt werden.\n\n## Recht auf Loeschung (Art. 17)\nDas 'Recht auf Vergessenwerden' ermoeglicht die Loeschung personenbezogener Daten.\n\n## Recht auf Einschraenkung (Art. 18)\nBetroffene koennen die Verarbeitung einschraenken lassen.\n\n## Recht auf Datenuebertragbarkeit (Art. 20)\nDaten muessen in einem maschinenlesbaren Format bereitgestellt werden.\n\n## Widerspruchsrecht (Art. 21)\nBetroffene koennen der Verarbeitung widersprechen.",
			},
			{
				Title:           "Datenschutz im Arbeitsalltag",
				Type:            "text",
				Order:           4,
				DurationMinutes: 15,
				ContentMarkdown: "# Datenschutz im Arbeitsalltag\n\n## E-Mails\n- Keine personenbezogenen Daten unverschluesselt versenden\n- BCC statt CC bei Massenversand\n- Vorsicht bei Anhangen\n\n## Bildschirmsperre\n- Computer bei Abwesenheit sperren (Win+L / Cmd+Ctrl+Q)\n- Automatische Sperre nach 5 Minuten\n\n## Clean Desk Policy\n- Keine sensiblen Dokumente offen liegen lassen\n- Aktenvernichter fuer Papierdokumente\n\n## Homeoffice\n- VPN nutzen\n- Kein oeffentliches WLAN fuer Firmendaten\n- Bildschirm vor Mitlesern schuetzen\n\n## Datenpannen melden\n- **Sofort** den Datenschutzbeauftragten informieren\n- Innerhalb von 72 Stunden an die Aufsichtsbehoerde\n- Dokumentation der Panne",
			},
			{
				Title:           "Wissenstest: DSGVO-Grundlagen",
				Type:            "quiz",
				Order:           5,
				DurationMinutes: 20,
				QuizQuestions: []AcademyQuizQuestion{
					{
						Question:           "Seit wann gilt die DSGVO?",
						Options:            []string{"1. Januar 2016", "25. Mai 2018", "1. Januar 2020", "25. Mai 2020"},
						CorrectOptionIndex: 1,
						Explanation:        "Die DSGVO gilt seit dem 25. Mai 2018 in allen EU-Mitgliedstaaten.",
						Order:              1,
					},
					{
						Question:           "Was sind personenbezogene Daten?",
						Options:            []string{"Nur Name und Adresse", "Alle Informationen, die sich auf eine identifizierbare Person beziehen", "Nur digitale Daten", "Nur sensible Gesundheitsdaten"},
						CorrectOptionIndex: 1,
						Explanation:        "Personenbezogene Daten umfassen alle Informationen, die sich auf eine identifizierte oder identifizierbare natuerliche Person beziehen.",
						Order:              2,
					},
					{
						Question:           "Wie hoch kann das Bussgeld bei DSGVO-Verstoessen maximal sein?",
						Options:            []string{"1 Mio. EUR", "5 Mio. EUR", "10 Mio. EUR oder 2% des Jahresumsatzes", "20 Mio. EUR oder 4% des Jahresumsatzes"},
						CorrectOptionIndex: 3,
						Explanation:        "Bei schwerwiegenden Verstoessen koennen Bussgelder von bis zu 20 Mio. EUR oder 4% des weltweiten Jahresumsatzes verhaengt werden.",
						Order:              3,
					},
					{
						Question:           "Was bedeutet das Prinzip der Datenminimierung?",
						Options:            []string{"Alle Daten muessen verschluesselt werden", "Es duerfen nur fuer den Zweck erforderliche Daten erhoben werden", "Daten muessen nach 30 Tagen geloescht werden", "Nur Administratoren duerfen auf Daten zugreifen"},
						CorrectOptionIndex: 1,
						Explanation:        "Datenminimierung bedeutet, dass nur die fuer den jeweiligen Zweck erforderlichen Daten erhoben und verarbeitet werden duerfen.",
						Order:              4,
					},
					{
						Question:           "Innerhalb welcher Frist muss eine Datenpanne der Aufsichtsbehoerde gemeldet werden?",
						Options:            []string{"24 Stunden", "48 Stunden", "72 Stunden", "7 Tage"},
						CorrectOptionIndex: 2,
						Explanation:        "Gemaess Art. 33 DSGVO muss eine Datenpanne innerhalb von 72 Stunden nach Bekanntwerden der Aufsichtsbehoerde gemeldet werden.",
						Order:              5,
					},
				},
			},
		},
	}
}

func (h *AcademyHandler) mockITSecurityCourse(req GenerateCourseRequest) AcademyCourse {
	return AcademyCourse{
		Title:           "IT-Sicherheit & Cybersecurity Awareness",
		Description:     "Sensibilisierung fuer IT-Sicherheitsrisiken und Best Practices im Umgang mit Phishing, Passwoertern und Social Engineering.",
		DurationMinutes: 60,
		Lessons: []AcademyLesson{
			{Title: "Phishing erkennen und vermeiden", Type: "text", Order: 1, DurationMinutes: 15,
				ContentMarkdown: "# Phishing erkennen\n\n## Typische Merkmale\n- Dringlichkeit ('Ihr Konto wird gesperrt!')\n- Unbekannter Absender\n- Verdaechtige Links\n- Rechtschreibfehler\n\n## Was tun bei Verdacht?\n1. Link NICHT anklicken\n2. Anhang NICHT oeffnen\n3. IT-Sicherheit informieren"},
			{Title: "Sichere Passwoerter und MFA", Type: "text", Order: 2, DurationMinutes: 15,
				ContentMarkdown: "# Sichere Passwoerter\n\n## Regeln\n- Mindestens 12 Zeichen\n- Gross-/Kleinbuchstaben, Zahlen, Sonderzeichen\n- Fuer jeden Dienst ein eigenes Passwort\n- Passwort-Manager verwenden\n\n## Multi-Faktor-Authentifizierung\n- Immer aktivieren wenn moeglich\n- App-basiert (z.B. Microsoft Authenticator) bevorzugen"},
			{Title: "Social Engineering", Type: "text", Order: 3, DurationMinutes: 15,
				ContentMarkdown: "# Social Engineering\n\nAngreifer nutzen menschliche Schwaechen aus.\n\n## Methoden\n- **Pretexting**: Falsche Identitaet vortaeuschen\n- **Tailgating**: Unbefugter Zutritt durch Hinterherfolgen\n- **CEO Fraud**: Gefaelschte Anweisungen vom Vorgesetzten\n\n## Schutz\n- Identitaet immer verifizieren\n- Bei Unsicherheit nachfragen"},
			{Title: "Wissenstest: IT-Sicherheit", Type: "quiz", Order: 4, DurationMinutes: 15,
				QuizQuestions: []AcademyQuizQuestion{
					{Question: "Was ist ein typisches Merkmal einer Phishing-E-Mail?", Options: []string{"Professionelles Design", "Kuenstliche Dringlichkeit", "Bekannter Absender", "Kurzer Text"}, CorrectOptionIndex: 1, Explanation: "Phishing-Mails erzeugen oft kuenstliche Dringlichkeit.", Order: 1},
					{Question: "Wie lang sollte ein sicheres Passwort mindestens sein?", Options: []string{"6 Zeichen", "8 Zeichen", "10 Zeichen", "12 Zeichen"}, CorrectOptionIndex: 3, Explanation: "Mindestens 12 Zeichen werden empfohlen.", Order: 2},
					{Question: "Was ist CEO Fraud?", Options: []string{"Hacker-Angriff auf Server", "Gefaelschte Anweisung vom Vorgesetzten", "Virus in E-Mail-Anhang", "DDoS-Attacke"}, CorrectOptionIndex: 1, Explanation: "CEO Fraud ist eine Social-Engineering-Methode mit gefaelschten Anweisungen.", Order: 3},
				}},
		},
	}
}

func (h *AcademyHandler) mockAILiteracyCourse(req GenerateCourseRequest) AcademyCourse {
	return AcademyCourse{
		Title:           "AI Literacy - Sicherer Umgang mit KI",
		Description:     "Grundlagen kuenstlicher Intelligenz, EU AI Act und verantwortungsvoller Einsatz von KI-Werkzeugen im Unternehmen.",
		DurationMinutes: 75,
		Lessons: []AcademyLesson{
			{Title: "Was ist Kuenstliche Intelligenz?", Type: "text", Order: 1, DurationMinutes: 15,
				ContentMarkdown: "# Was ist KI?\n\nKuenstliche Intelligenz (KI) bezeichnet Systeme, die menschenaehnliche kognitive Faehigkeiten zeigen.\n\n## Arten von KI\n- **Machine Learning**: Lernt aus Daten\n- **Deep Learning**: Neuronale Netze\n- **Generative AI**: Erstellt neue Inhalte (Text, Bild)\n- **LLMs**: Large Language Models wie ChatGPT"},
			{Title: "Der EU AI Act", Type: "text", Order: 2, DurationMinutes: 20,
				ContentMarkdown: "# EU AI Act\n\n## Risikoklassen\n- **Unakzeptabel**: Social Scoring, Manipulation\n- **Hochrisiko**: Bildung, HR, Kritische Infrastruktur\n- **Begrenzt**: Chatbots, Empfehlungssysteme\n- **Minimal**: Spam-Filter\n\n## Art. 4: AI Literacy Pflicht\nAlle Mitarbeiter, die KI-Systeme nutzen, muessen geschult werden."},
			{Title: "KI sicher im Unternehmen nutzen", Type: "text", Order: 3, DurationMinutes: 20,
				ContentMarkdown: "# KI sicher nutzen\n\n## Dos\n- Ergebnisse immer pruefen\n- Keine vertraulichen Daten eingeben\n- Firmenpolicies beachten\n\n## Don'ts\n- Blindes Vertrauen in KI-Ergebnisse\n- Personenbezogene Daten in externe KI-Tools\n- KI-generierte Inhalte ohne Pruefung veroeffentlichen"},
			{Title: "Wissenstest: AI Literacy", Type: "quiz", Order: 4, DurationMinutes: 20,
				QuizQuestions: []AcademyQuizQuestion{
					{Question: "Was verlangt Art. 4 des EU AI Acts?", Options: []string{"Verbot aller KI-Systeme", "AI Literacy Schulung fuer KI-Nutzer", "Nur Open-Source KI erlaubt", "KI nur in der IT-Abteilung"}, CorrectOptionIndex: 1, Explanation: "Art. 4 EU AI Act fordert AI Literacy fuer alle Mitarbeiter, die KI-Systeme nutzen.", Order: 1},
					{Question: "Duerfen vertrauliche Firmendaten in externe KI-Tools eingegeben werden?", Options: []string{"Ja, immer", "Nur in ChatGPT", "Nein, grundsaetzlich nicht", "Nur mit VPN"}, CorrectOptionIndex: 2, Explanation: "Vertrauliche Daten duerfen nicht in externe KI-Tools eingegeben werden.", Order: 2},
				}},
		},
	}
}

func (h *AcademyHandler) mockWhistleblowerCourse(req GenerateCourseRequest) AcademyCourse {
	return AcademyCourse{
		Title:           "Hinweisgeberschutz (HinSchG)",
		Description:     "Einführung in das Hinweisgeberschutzgesetz, interne Meldewege und Schutz von Whistleblowern.",
		DurationMinutes: 45,
		Lessons: []AcademyLesson{
			{Title: "Das Hinweisgeberschutzgesetz", Type: "text", Order: 1, DurationMinutes: 15,
				ContentMarkdown: "# Hinweisgeberschutzgesetz (HinSchG)\n\nSeit Juli 2023 muessen Unternehmen ab 50 Mitarbeitern interne Meldestellen einrichten.\n\n## Was ist geschuetzt?\n- Meldungen ueber Rechtsverstoesse\n- Verstoesse gegen EU-Recht\n- Straftaten und Ordnungswidrigkeiten"},
			{Title: "Interne Meldewege", Type: "text", Order: 2, DurationMinutes: 15,
				ContentMarkdown: "# Interne Meldewege\n\n## Wie melde ich einen Verstoss?\n1. **Interne Meldestelle** (bevorzugt)\n2. **Externe Meldestelle** (BfJ)\n3. **Offenlegung** (nur als letztes Mittel)\n\n## Schutz fuer Hinweisgeber\n- Kuendigungsschutz\n- Keine Benachteiligung\n- Vertraulichkeit"},
			{Title: "Wissenstest: Hinweisgeberschutz", Type: "quiz", Order: 3, DurationMinutes: 15,
				QuizQuestions: []AcademyQuizQuestion{
					{Question: "Ab wie vielen Mitarbeitern muessen Unternehmen eine Meldestelle einrichten?", Options: []string{"10", "25", "50", "250"}, CorrectOptionIndex: 2, Explanation: "Unternehmen ab 50 Beschaeftigten muessen eine interne Meldestelle einrichten.", Order: 1},
					{Question: "Welche Meldung ist NICHT durch das HinSchG geschuetzt?", Options: []string{"Straftaten", "Verstoesse gegen EU-Recht", "Persoenliche Beschwerden ueber Kollegen", "Umweltverstoesse"}, CorrectOptionIndex: 2, Explanation: "Persoenliche Konflikte fallen nicht unter das HinSchG.", Order: 2},
				}},
		},
	}
}
