package handlers

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

type QueueHandler struct {
	pool         *pgxpool.Pool
	queueService *services.QueueService
}

func NewQueueHandler(pool *pgxpool.Pool, queueService *services.QueueService) *QueueHandler {
	return &QueueHandler{pool: pool, queueService: queueService}
}

func (h *QueueHandler) Enter(c *gin.Context) {
	var req models.QueueEnterRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.BadRequest(c, "eventId is required")
		return
	}

	userID, _ := c.Get("userId")
	ipAddress := c.ClientIP()

	entry, err := h.queueService.EnqueueUser(req.EventID, userID.(string), ipAddress)
	if err != nil {
		utils.BadRequest(c, err.Error())
		return
	}

	// Calculate estimated wait
	estimatedWait := h.queueService.EstimateWaitTime(req.EventID, entry.Position)

	utils.Success(c, gin.H{
		"queueEntry": entry,
		"estimatedWaitMinutes": estimatedWait,
	})
}

func (h *QueueHandler) Status(c *gin.Context) {
	eventID := c.Query("eventId")
	if eventID == "" {
		utils.BadRequest(c, "eventId is required")
		return
	}

	userID, _ := c.Get("userId")

	entry, err := h.queueService.GetQueueStatus(eventID, userID.(string))
	if err != nil {
		utils.InternalError(c, "Failed to check queue status")
		return
	}

	if entry == nil {
		utils.NotFound(c, "Not in queue")
		return
	}

	estimatedWait := h.queueService.EstimateWaitTime(eventID, entry.Position)

	utils.Success(c, gin.H{
		"status": gin.H{
			"id":                  entry.ID,
			"position":            entry.Position,
			"status":              entry.Status,
			"estimatedWaitMinutes": estimatedWait,
			"enteredAt":           entry.EnteredAt,
			"activatedAt":         entry.ActivatedAt,
			"expiresAt":           entry.ExpiresAt,
		},
	})
}

func (h *QueueHandler) Activate(c *gin.Context) {
	var req models.QueueActivateRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.BadRequest(c, "eventId is required")
		return
	}

	userID, _ := c.Get("userId")

	// Check if already active
	active, _ := h.queueService.IsSessionActive(req.EventID, userID.(string))
	if active {
		utils.Success(c, gin.H{"message": "Already active"})
		return
	}

	if err := h.queueService.ActivateSession(req.EventID, userID.(string)); err != nil {
		utils.BadRequest(c, err.Error())
		return
	}

	utils.Success(c, gin.H{"message": "Session activated"})
}

func (h *QueueHandler) Test(c *gin.Context) {
	utils.Success(c, gin.H{"message": "Queue system is running"})
}

func (h *QueueHandler) Simulate(c *gin.Context) {
	var req struct {
		EventID string `json:"eventId" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		utils.BadRequest(c, "eventId is required")
		return
	}

	// Process expired sessions and activate next users
	expired, _ := h.queueService.ProcessExpiredSessions(req.EventID)
	h.queueService.GetNextInQueue(req.EventID, 5)

	utils.Success(c, gin.H{
		"message":        "Queue progress simulated",
		"expiredSessions": expired,
	})
}
