package handlers

import (
	"net/http"

	"github.com/breakpilot/edu-search-service/internal/orchestrator"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// OrchestratorHandler handles orchestrator-related HTTP requests
type OrchestratorHandler struct {
	orchestrator *orchestrator.Orchestrator
	repo         orchestrator.Repository
}

// NewOrchestratorHandler creates a new orchestrator handler
func NewOrchestratorHandler(orch *orchestrator.Orchestrator, repo orchestrator.Repository) *OrchestratorHandler {
	return &OrchestratorHandler{
		orchestrator: orch,
		repo:         repo,
	}
}

// AddToQueueRequest represents a request to add a university to the crawl queue
type AddToQueueRequest struct {
	UniversityID string `json:"university_id" binding:"required"`
	Priority     int    `json:"priority"`
	InitiatedBy  string `json:"initiated_by"`
}

// GetStatus returns the current orchestrator status
func (h *OrchestratorHandler) GetStatus(c *gin.Context) {
	status, err := h.orchestrator.Status(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get status", "details": err.Error()})
		return
	}

	c.JSON(http.StatusOK, status)
}

// GetQueue returns all items in the crawl queue
func (h *OrchestratorHandler) GetQueue(c *gin.Context) {
	items, err := h.orchestrator.GetQueue(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get queue", "details": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"queue": items,
		"count": len(items),
	})
}

// AddToQueue adds a university to the crawl queue
func (h *OrchestratorHandler) AddToQueue(c *gin.Context) {
	var req AddToQueueRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
		return
	}

	universityID, err := uuid.Parse(req.UniversityID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid university_id format"})
		return
	}

	// Default priority if not specified
	priority := req.Priority
	if priority == 0 {
		priority = 5
	}

	initiatedBy := req.InitiatedBy
	if initiatedBy == "" {
		initiatedBy = "api"
	}

	item, err := h.orchestrator.AddUniversity(c.Request.Context(), universityID, priority, initiatedBy)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to add to queue", "details": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, item)
}

// RemoveFromQueue removes a university from the crawl queue
func (h *OrchestratorHandler) RemoveFromQueue(c *gin.Context) {
	idStr := c.Param("id")
	if idStr == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "University ID required"})
		return
	}

	universityID, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid university_id format"})
		return
	}

	if err := h.orchestrator.RemoveUniversity(c.Request.Context(), universityID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to remove from queue", "details": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"deleted": true, "university_id": idStr})
}

// Start starts the orchestrator
func (h *OrchestratorHandler) Start(c *gin.Context) {
	if err := h.orchestrator.Start(); err != nil {
		c.JSON(http.StatusConflict, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  "started",
		"message": "Orchestrator started successfully",
	})
}

// Stop stops the orchestrator
func (h *OrchestratorHandler) Stop(c *gin.Context) {
	if err := h.orchestrator.Stop(); err != nil {
		c.JSON(http.StatusConflict, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":  "stopped",
		"message": "Orchestrator stopped successfully",
	})
}

// PauseUniversity pauses crawling for a specific university
func (h *OrchestratorHandler) PauseUniversity(c *gin.Context) {
	idStr := c.Param("id")
	if idStr == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "University ID required"})
		return
	}

	universityID, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid university_id format"})
		return
	}

	if err := h.orchestrator.PauseUniversity(c.Request.Context(), universityID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to pause crawl", "details": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":        "paused",
		"university_id": idStr,
	})
}

// ResumeUniversity resumes crawling for a paused university
func (h *OrchestratorHandler) ResumeUniversity(c *gin.Context) {
	idStr := c.Param("id")
	if idStr == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "University ID required"})
		return
	}

	universityID, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid university_id format"})
		return
	}

	if err := h.orchestrator.ResumeUniversity(c.Request.Context(), universityID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to resume crawl", "details": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":        "resumed",
		"university_id": idStr,
	})
}

// SetupOrchestratorRoutes configures orchestrator API routes
func SetupOrchestratorRoutes(r *gin.RouterGroup, h *OrchestratorHandler) {
	crawl := r.Group("/crawl")
	{
		// Orchestrator control
		crawl.GET("/status", h.GetStatus)
		crawl.POST("/start", h.Start)
		crawl.POST("/stop", h.Stop)

		// Queue management
		crawl.GET("/queue", h.GetQueue)
		crawl.POST("/queue", h.AddToQueue)
		crawl.DELETE("/queue/:id", h.RemoveFromQueue)

		// Individual university control
		crawl.POST("/queue/:id/pause", h.PauseUniversity)
		crawl.POST("/queue/:id/resume", h.ResumeUniversity)
	}
}
