package handlers

import (
	"net/http"
	"time"

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

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

// ========================================
// Attendance Handlers
// ========================================

// RecordAttendance records attendance for a student
// POST /api/v1/attendance
func (h *SchoolHandlers) RecordAttendance(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.RecordAttendanceRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	record, err := h.attendanceService.RecordAttendance(c.Request.Context(), req, userID.(uuid.UUID))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, record)
}

// RecordBulkAttendance records attendance for multiple students
// POST /api/v1/classes/:id/attendance
func (h *SchoolHandlers) RecordBulkAttendance(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}

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

	var req struct {
		Date    string `json:"date" binding:"required"`
		SlotID  string `json:"slot_id" binding:"required"`
		Records []struct {
			StudentID string  `json:"student_id"`
			Status    string  `json:"status"`
			Note      *string `json:"note"`
		} `json:"records" binding:"required"`
	}

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

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

	// Convert to the expected type (without JSON tags)
	records := make([]struct {
		StudentID string
		Status    string
		Note      *string
	}, len(req.Records))
	for i, r := range req.Records {
		records[i] = struct {
			StudentID string
			Status    string
			Note      *string
		}{
			StudentID: r.StudentID,
			Status:    r.Status,
			Note:      r.Note,
		}
	}

	err = h.attendanceService.RecordBulkAttendance(c.Request.Context(), classID, req.Date, slotID, records, userID.(uuid.UUID))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "attendance recorded"})
}

// GetClassAttendance gets attendance for a class on a specific date
// GET /api/v1/classes/:id/attendance?date=...
func (h *SchoolHandlers) GetClassAttendance(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
	}

	date := c.Query("date")
	if date == "" {
		date = time.Now().Format("2006-01-02")
	}

	overview, err := h.attendanceService.GetAttendanceByClass(c.Request.Context(), classID, date)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, overview)
}

// GetStudentAttendance gets attendance history for a student
// GET /api/v1/students/:id/attendance?start_date=...&end_date=...
func (h *SchoolHandlers) GetStudentAttendance(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
	}

	startDateStr := c.Query("start_date")
	endDateStr := c.Query("end_date")

	var startDate, endDate time.Time
	if startDateStr == "" {
		startDate = time.Now().AddDate(0, -1, 0) // Last month
	} else {
		startDate, _ = time.Parse("2006-01-02", startDateStr)
	}

	if endDateStr == "" {
		endDate = time.Now()
	} else {
		endDate, _ = time.Parse("2006-01-02", endDateStr)
	}

	records, err := h.attendanceService.GetStudentAttendance(c.Request.Context(), studentID, startDate, endDate)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, records)
}

// ========================================
// Absence Report Handlers
// ========================================

// ReportAbsence allows parents to report absence
// POST /api/v1/absence/report
func (h *SchoolHandlers) ReportAbsence(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.ReportAbsenceRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	report, err := h.attendanceService.ReportAbsence(c.Request.Context(), req, userID.(uuid.UUID))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, report)
}

// ConfirmAbsence allows teachers to confirm absence
// PUT /api/v1/absence/:id/confirm
func (h *SchoolHandlers) ConfirmAbsence(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}

	reportIDStr := c.Param("id")
	reportID, err := uuid.Parse(reportIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid report ID"})
		return
	}

	var req struct {
		Status string `json:"status" binding:"required"` // "excused" or "unexcused"
	}

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

	err = h.attendanceService.ConfirmAbsence(c.Request.Context(), reportID, userID.(uuid.UUID), req.Status)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "absence confirmed"})
}

// GetPendingAbsenceReports gets pending absence reports for a class
// GET /api/v1/classes/:id/absence/pending
func (h *SchoolHandlers) GetPendingAbsenceReports(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
	}

	reports, err := h.attendanceService.GetPendingAbsenceReports(c.Request.Context(), classID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, reports)
}
