package handlers

import (
	"github.com/gin-gonic/gin"
	"github.com/jackc/pgx/v5/pgxpool"
	"ticketing-backend/internal/utils"
)

type WaliKelasHandler struct {
	pool *pgxpool.Pool
}

func NewWaliKelasHandler(pool *pgxpool.Pool) *WaliKelasHandler {
	return &WaliKelasHandler{pool: pool}
}

func (h *WaliKelasHandler) ListClasses(c *gin.Context) {
	userID, _ := c.Get("userId")

	rows, err := h.pool.Query(c.Request.Context(),
		`SELECT DISTINCT c.id, c.name
		 FROM classes c
		 JOIN wali_kelas_classes wkc ON wkc.class_id = c.id
		 WHERE wkc.wali_kelas_id = $1
		 ORDER BY c.name ASC`, userID,
	)
	if err != nil {
		utils.InternalError(c, "Failed to fetch classes")
		return
	}
	defer rows.Close()

	var classes []gin.H
	for rows.Next() {
		var id, name string
		rows.Scan(&id, &name)
		classes = append(classes, gin.H{"id": id, "name": name})
	}

	utils.Success(c, gin.H{"classes": classes})
}

func (h *WaliKelasHandler) ListEvents(c *gin.Context) {
	rows, err := h.pool.Query(c.Request.Context(),
		`SELECT e.id, e.name, e.description, e.venue, e.event_date,
		        e.total_capacity, e.remaining_capacity, e.status
		 FROM events e
		 WHERE e.status IN ('published', 'active')
		 ORDER BY e.event_date ASC`)
	if err != nil {
		utils.InternalError(c, "Failed to fetch events")
		return
	}
	defer rows.Close()

	var events []gin.H
	for rows.Next() {
		var id, name, venue, status string
		var desc *string
		var eventDate string
		var total, remaining int
		rows.Scan(&id, &name, &desc, &venue, &eventDate, &total, &remaining, &status)
		events = append(events, gin.H{
			"id": id, "name": name, "description": desc, "venue": venue,
			"event_date": eventDate, "total_capacity": total,
			"remaining_capacity": remaining, "status": status,
		})
	}

	utils.Success(c, gin.H{"events": events})
}

func (h *WaliKelasHandler) GetEvent(c *gin.Context) {
	eventID := c.Param("eventId")

	var event struct {
		ID                string  `json:"id"`
		Name              string  `json:"name"`
		Description       *string `json:"description"`
		Venue             string  `json:"venue"`
		EventDate         string  `json:"event_date"`
		TotalCapacity     int     `json:"total_capacity"`
		RemainingCapacity int     `json:"remaining_capacity"`
		Status            string  `json:"status"`
	}
	err := h.pool.QueryRow(c.Request.Context(),
		`SELECT id, name, description, venue, event_date, total_capacity,
		        remaining_capacity, status FROM events WHERE id = $1`, eventID,
	).Scan(&event.ID, &event.Name, &event.Description, &event.Venue, &event.EventDate,
		&event.TotalCapacity, &event.RemainingCapacity, &event.Status)
	if err != nil {
		utils.NotFound(c, "Event not found")
		return
	}

	// Get ticket classes
	tcRows, _ := h.pool.Query(c.Request.Context(),
		`SELECT id, name, price, remaining_capacity, description
		 FROM ticket_classes WHERE event_id = $1 ORDER BY price ASC`, eventID)
	defer tcRows.Close()

	var ticketClasses []gin.H
	for tcRows.Next() {
		var id, name string
		var price float64
		var remaining int
		var desc *string
		tcRows.Scan(&id, &name, &price, &remaining, &desc)
		ticketClasses = append(ticketClasses, gin.H{
			"id": id, "name": name, "price": price,
			"remaining_capacity": remaining, "description": desc,
		})
	}

	utils.Success(c, gin.H{
		"event":         event,
		"ticketClasses": ticketClasses,
	})
}

func (h *WaliKelasHandler) ListStudents(c *gin.Context) {
	userID, _ := c.Get("userId")

	// Get classes assigned to this wali kelas
	rows, err := h.pool.Query(c.Request.Context(),
		`SELECT u.id, u.email, u.full_name
		 FROM users u
		 JOIN wali_kelas_classes wkc ON wkc.class_id = u.class_id
		 WHERE wkc.wali_kelas_id = $1 AND u.role = 'visitor'
		 ORDER BY u.full_name ASC`, userID,
	)
	if err != nil {
		utils.InternalError(c, "Failed to fetch students")
		return
	}
	defer rows.Close()

	var students []gin.H
	for rows.Next() {
		var id, email, fName string
		rows.Scan(&id, &email, &fName)
		students = append(students, gin.H{"id": id, "email": email, "full_name": fName})
	}

	utils.Success(c, gin.H{"students": students})
}

func (h *WaliKelasHandler) ListOrders(c *gin.Context) {
	userID, _ := c.Get("userId")

	rows, err := h.pool.Query(c.Request.Context(),
		`SELECT wo.id, wo.student_id, wo.event_id, wo.ticket_class_id, wo.quantity,
		        wo.notes, wo.created_at,
		        u.full_name as student_name, e.name as event_name,
		        tc.name as ticket_class_name, o.status as order_status
		 FROM wali_kelas_orders wo
		 JOIN users u ON u.id = wo.student_id
		 JOIN events e ON e.id = wo.event_id
		 JOIN ticket_classes tc ON tc.id = wo.ticket_class_id
		 JOIN orders o ON o.id = wo.order_id
		 WHERE wo.wali_kelas_id = $1
		 ORDER BY wo.created_at DESC`, userID,
	)
	if err != nil {
		utils.InternalError(c, "Failed to fetch orders")
		return
	}
	defer rows.Close()

	var orders []gin.H
	for rows.Next() {
		var id, studentID, eventID, tcID, sName, eName, tcName, oStatus, createdAt string
		var qty int
		var notes *string
		rows.Scan(&id, &studentID, &eventID, &tcID, &qty, &notes, &createdAt, &sName, &eName, &tcName, &oStatus)
		orders = append(orders, gin.H{
			"id": id, "student_id": studentID, "event_id": eventID,
			"ticket_class_id": tcID, "quantity": qty, "notes": notes,
			"created_at": createdAt, "student_name": sName, "event_name": eName,
			"ticket_class_name": tcName, "order_status": oStatus,
		})
	}

	utils.Success(c, gin.H{"orders": orders})
}

func (h *WaliKelasHandler) ImportOrders(c *gin.Context) {
	_, _ = c.Get("userId")

	file, _, err := c.Request.FormFile("file")
	if err != nil {
		utils.BadRequest(c, "File is required")
		return
	}
	defer file.Close()

	utils.Success(c, gin.H{"message": "Import started"})
}

func (h *WaliKelasHandler) DownloadTemplate(c *gin.Context) {
	utils.Success(c, gin.H{"message": "Template download endpoint"})
}
