package handlers

import (
	"net/http"

	"github.com/breakpilot/consent-service/internal/models"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// ========================================
// Grade Handlers
// ========================================

// CreateGrade creates a new grade
// POST /api/v1/grades
func (h *SchoolHandlers) CreateGrade(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}

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

	// Get teacher ID from user ID
	teacher, err := h.schoolService.GetTeacherByUserID(c.Request.Context(), userID.(uuid.UUID))
	if err != nil {
		c.JSON(http.StatusForbidden, gin.H{"error": "user is not a teacher"})
		return
	}

	grade, err := h.gradeService.CreateGrade(c.Request.Context(), req, teacher.ID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, grade)
}

// GetStudentGrades gets all grades for a student
// GET /api/v1/students/:id/grades?school_year_id=...
func (h *SchoolHandlers) GetStudentGrades(c *gin.Context) {
	studentIDStr := c.Param("id")
	studentID, err := uuid.Parse(studentIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid student ID"})
		return
	}

	schoolYearIDStr := c.Query("school_year_id")
	if schoolYearIDStr == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "school_year_id is required"})
		return
	}

	schoolYearID, err := uuid.Parse(schoolYearIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid school year ID"})
		return
	}

	grades, err := h.gradeService.GetStudentGrades(c.Request.Context(), studentID, schoolYearID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, grades)
}

// GetClassGrades gets grades for all students in a class for a subject (Notenspiegel)
// GET /api/v1/classes/:id/grades/:subjectId?school_year_id=...&semester=...
func (h *SchoolHandlers) GetClassGrades(c *gin.Context) {
	classIDStr := c.Param("id")
	classID, err := uuid.Parse(classIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid class ID"})
		return
	}

	subjectIDStr := c.Param("subjectId")
	subjectID, err := uuid.Parse(subjectIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid subject ID"})
		return
	}

	schoolYearIDStr := c.Query("school_year_id")
	if schoolYearIDStr == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "school_year_id is required"})
		return
	}

	schoolYearID, err := uuid.Parse(schoolYearIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid school year ID"})
		return
	}

	semesterStr := c.DefaultQuery("semester", "1")
	var semester int
	if semesterStr == "1" {
		semester = 1
	} else {
		semester = 2
	}

	overviews, err := h.gradeService.GetClassGradesBySubject(c.Request.Context(), classID, subjectID, schoolYearID, semester)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, overviews)
}

// GetGradeStatistics gets grade statistics for a class/subject
// GET /api/v1/classes/:id/grades/:subjectId/stats?school_year_id=...&semester=...
func (h *SchoolHandlers) GetGradeStatistics(c *gin.Context) {
	classIDStr := c.Param("id")
	classID, err := uuid.Parse(classIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid class ID"})
		return
	}

	subjectIDStr := c.Param("subjectId")
	subjectID, err := uuid.Parse(subjectIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid subject ID"})
		return
	}

	schoolYearIDStr := c.Query("school_year_id")
	if schoolYearIDStr == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "school_year_id is required"})
		return
	}

	schoolYearID, err := uuid.Parse(schoolYearIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid school year ID"})
		return
	}

	semesterStr := c.DefaultQuery("semester", "1")
	var semester int
	if semesterStr == "1" {
		semester = 1
	} else {
		semester = 2
	}

	stats, err := h.gradeService.GetSubjectGradeStatistics(c.Request.Context(), classID, subjectID, schoolYearID, semester)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, stats)
}

// ========================================
// Parent Onboarding Handlers
// ========================================

// GenerateOnboardingToken generates a QR code token for parent onboarding
// POST /api/v1/onboarding/tokens
func (h *SchoolHandlers) GenerateOnboardingToken(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}

	var req struct {
		SchoolID  string `json:"school_id" binding:"required"`
		ClassID   string `json:"class_id" binding:"required"`
		StudentID string `json:"student_id" binding:"required"`
		Role      string `json:"role"` // "parent" or "parent_representative"
	}

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

	schoolID, err := uuid.Parse(req.SchoolID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid school ID"})
		return
	}

	classID, err := uuid.Parse(req.ClassID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid class ID"})
		return
	}

	studentID, err := uuid.Parse(req.StudentID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid student ID"})
		return
	}

	role := req.Role
	if role == "" {
		role = "parent"
	}

	token, err := h.schoolService.GenerateParentOnboardingToken(c.Request.Context(), schoolID, classID, studentID, userID.(uuid.UUID), role)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Generate QR code URL
	qrURL := "/onboard-parent?token=" + token.Token

	c.JSON(http.StatusCreated, gin.H{
		"token":      token.Token,
		"qr_url":     qrURL,
		"expires_at": token.ExpiresAt,
	})
}

// ValidateOnboardingToken validates an onboarding token
// GET /api/v1/onboarding/validate?token=...
func (h *SchoolHandlers) ValidateOnboardingToken(c *gin.Context) {
	token := c.Query("token")
	if token == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "token is required"})
		return
	}

	onboardingToken, err := h.schoolService.ValidateOnboardingToken(c.Request.Context(), token)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "invalid or expired token"})
		return
	}

	// Get student and school info
	student, err := h.schoolService.GetStudent(c.Request.Context(), onboardingToken.StudentID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	class, err := h.schoolService.GetClass(c.Request.Context(), onboardingToken.ClassID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	school, err := h.schoolService.GetSchool(c.Request.Context(), onboardingToken.SchoolID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"valid":        true,
		"role":         onboardingToken.Role,
		"student_name": student.FirstName + " " + student.LastName,
		"class_name":   class.Name,
		"school_name":  school.Name,
		"expires_at":   onboardingToken.ExpiresAt,
	})
}

// RedeemOnboardingToken redeems a token and creates parent account
// POST /api/v1/onboarding/redeem
func (h *SchoolHandlers) RedeemOnboardingToken(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}

	var req struct {
		Token string `json:"token" binding:"required"`
	}

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

	err := h.schoolService.RedeemOnboardingToken(c.Request.Context(), req.Token, userID.(uuid.UUID))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "token redeemed successfully"})
}
