package handlers

import (
	"net/http"
	"strconv"
	"strings"

	"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"
)

// AcademyHandlers handles academy HTTP requests
type AcademyHandlers struct {
	store         *academy.Store
	trainingStore *training.Store
}

// NewAcademyHandlers creates new academy handlers
func NewAcademyHandlers(store *academy.Store, trainingStore *training.Store) *AcademyHandlers {
	return &AcademyHandlers{store: store, trainingStore: trainingStore}
}

// ============================================================================
// Course Management
// ============================================================================

// CreateCourse creates a new compliance training course
// POST /sdk/v1/academy/courses
func (h *AcademyHandlers) CreateCourse(c *gin.Context) {
	var req academy.CreateCourseRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	tenantID := rbac.GetTenantID(c)

	course := &academy.Course{
		TenantID:         tenantID,
		Title:            req.Title,
		Description:      req.Description,
		Category:         req.Category,
		DurationMinutes:  req.DurationMinutes,
		RequiredForRoles: req.RequiredForRoles,
		IsActive:         true,
	}

	if course.RequiredForRoles == nil {
		course.RequiredForRoles = []string{}
	}

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

	// Create lessons if provided
	for i := range req.Lessons {
		lesson := &academy.Lesson{
			CourseID:        course.ID,
			Title:           req.Lessons[i].Title,
			Description:     req.Lessons[i].Description,
			LessonType:      req.Lessons[i].LessonType,
			ContentURL:      req.Lessons[i].ContentURL,
			DurationMinutes: req.Lessons[i].DurationMinutes,
			OrderIndex:      req.Lessons[i].OrderIndex,
			QuizQuestions:   req.Lessons[i].QuizQuestions,
		}
		if err := h.store.CreateLesson(c.Request.Context(), lesson); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
			return
		}
		course.Lessons = append(course.Lessons, *lesson)
	}

	if course.Lessons == nil {
		course.Lessons = []academy.Lesson{}
	}

	c.JSON(http.StatusCreated, gin.H{"course": course})
}

// GetCourse retrieves a course with its lessons
// GET /sdk/v1/academy/courses/:id
func (h *AcademyHandlers) GetCourse(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid course ID"})
		return
	}

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

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

// ListCourses lists courses for the current tenant
// GET /sdk/v1/academy/courses
func (h *AcademyHandlers) ListCourses(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

	filters := &academy.CourseFilters{
		Limit: 50,
	}

	if category := c.Query("category"); category != "" {
		filters.Category = academy.CourseCategory(category)
	}
	if search := c.Query("search"); search != "" {
		filters.Search = search
	}
	if activeStr := c.Query("is_active"); activeStr != "" {
		active := activeStr == "true"
		filters.IsActive = &active
	}
	if limitStr := c.Query("limit"); limitStr != "" {
		if limit, err := strconv.Atoi(limitStr); err == nil && limit > 0 {
			filters.Limit = limit
		}
	}
	if offsetStr := c.Query("offset"); offsetStr != "" {
		if offset, err := strconv.Atoi(offsetStr); err == nil && offset >= 0 {
			filters.Offset = offset
		}
	}

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

	c.JSON(http.StatusOK, academy.CourseListResponse{
		Courses: courses,
		Total:   total,
	})
}

// UpdateCourse updates a course
// PUT /sdk/v1/academy/courses/:id
func (h *AcademyHandlers) UpdateCourse(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid course ID"})
		return
	}

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

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

	if req.Title != nil {
		course.Title = *req.Title
	}
	if req.Description != nil {
		course.Description = *req.Description
	}
	if req.Category != nil {
		course.Category = *req.Category
	}
	if req.DurationMinutes != nil {
		course.DurationMinutes = *req.DurationMinutes
	}
	if req.RequiredForRoles != nil {
		course.RequiredForRoles = req.RequiredForRoles
	}
	if req.IsActive != nil {
		course.IsActive = *req.IsActive
	}

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

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

// DeleteCourse deletes a course
// DELETE /sdk/v1/academy/courses/:id
func (h *AcademyHandlers) DeleteCourse(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid course ID"})
		return
	}

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

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

// estimateReadingTime estimates reading time in minutes from markdown content
// Average reading speed: ~200 words per minute
func estimateReadingTime(content string) int {
	words := len(strings.Fields(content))
	minutes := words / 200
	if minutes < 5 {
		minutes = 5
	}
	return minutes
}
