package handlers

import (
	"context"
	"net/http"

	"github.com/google/uuid"

	// "strconv" // Removed this import

	apperrors "veza-backend-api/internal/errors"
	"veza-backend-api/internal/services"

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

// HLSServiceInterface defines methods needed for HLS handler
type HLSServiceInterface interface {
	GetMasterPlaylist(ctx context.Context, trackID uuid.UUID) (string, error)
	GetQualityPlaylist(ctx context.Context, trackID uuid.UUID, bitrate string) (string, error)
	GetSegmentPath(ctx context.Context, trackID uuid.UUID, bitrate string, segment string) (string, error)
	GetStreamInfo(ctx context.Context, trackID uuid.UUID) (map[string]interface{}, error)
	GetStreamStatus(ctx context.Context, trackID uuid.UUID) (map[string]interface{}, error)
	TriggerTranscodeQueue(ctx context.Context, trackID uuid.UUID, userID uuid.UUID) (uuid.UUID, error)
}

// HLSHandler gère les requêtes pour servir les fichiers HLS
type HLSHandler struct {
	hlsService HLSServiceInterface
}

// NewHLSHandler crée un nouveau handler HLS
func NewHLSHandler(hlsService *services.HLSService) *HLSHandler {
	return NewHLSHandlerWithInterface(hlsService)
}

// NewHLSHandlerWithInterface crée un nouveau handler HLS avec une interface (pour tests)
func NewHLSHandlerWithInterface(hlsService HLSServiceInterface) *HLSHandler {
	return &HLSHandler{hlsService: hlsService}
}

// ServeMasterPlaylist sert le master playlist pour un track
func (h *HLSHandler) ServeMasterPlaylist(c *gin.Context) {
	trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
		return
	}

	playlist, err := h.hlsService.GetMasterPlaylist(c.Request.Context(), trackID)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "playlist not found"})
		return
	}

	c.Header("Content-Type", "application/vnd.apple.mpegurl")
	c.Header("Cache-Control", "no-cache")
	c.String(http.StatusOK, playlist)
}

// ServeQualityPlaylist sert une quality playlist pour un track et bitrate
func (h *HLSHandler) ServeQualityPlaylist(c *gin.Context) {
	trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
		return
	}

	bitrate := c.Param("bitrate")
	playlist, err := h.hlsService.GetQualityPlaylist(c.Request.Context(), trackID, bitrate)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "playlist not found"})
		return
	}

	c.Header("Content-Type", "application/vnd.apple.mpegurl")
	c.Header("Cache-Control", "no-cache")
	c.String(http.StatusOK, playlist)
}

// ServeSegment sert un segment pour un track, bitrate et nom de segment
func (h *HLSHandler) ServeSegment(c *gin.Context) {
	trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
		return
	}

	bitrate := c.Param("bitrate")
	segment := c.Param("segment")

	segmentPath, err := h.hlsService.GetSegmentPath(c.Request.Context(), trackID, bitrate, segment)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "segment not found"})
		return
	}

	c.Header("Content-Type", "video/mp2t")
	c.Header("Cache-Control", "public, max-age=3600")
	c.File(segmentPath)
}

// GetStreamInfo retourne les informations générales d'un stream HLS pour un track
// GET /api/v1/tracks/:id/hls/info
// BE-API-020: Implement HLS stream info endpoint
func (h *HLSHandler) GetStreamInfo(c *gin.Context) {
	trackID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		RespondWithAppError(c, apperrors.NewValidationError("invalid track id"))
		return
	}

	info, err := h.hlsService.GetStreamInfo(c.Request.Context(), trackID)
	if err != nil {
		if err.Error()[:20] == "HLS stream not found" {
			RespondWithAppError(c, apperrors.NewNotFoundError("HLS stream"))
			return
		}
		RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "failed to get stream info", err))
		return
	}

	RespondSuccess(c, http.StatusOK, info)
}

// GetStreamStatus retourne le statut d'un stream HLS pour un track
// GET /api/v1/tracks/:id/hls/status
// BE-API-020: Implement HLS stream info endpoint
func (h *HLSHandler) GetStreamStatus(c *gin.Context) {
	trackID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		RespondWithAppError(c, apperrors.NewValidationError("invalid track id"))
		return
	}

	status, err := h.hlsService.GetStreamStatus(c.Request.Context(), trackID)
	if err != nil {
		if err.Error()[:20] == "HLS stream not found" {
			RespondWithAppError(c, apperrors.NewNotFoundError("HLS stream"))
			return
		}
		RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "failed to get stream status", err))
		return
	}

	RespondSuccess(c, http.StatusOK, status)
}

// TriggerTranscode déclenche le transcodage HLS d'un track via la queue (T0343)
func (h *HLSHandler) TriggerTranscode(c *gin.Context) {
	userID, ok := GetUserIDUUID(c)
	if !ok {
		return // Erreur déjà envoyée par GetUserIDUUID
	}
	if userID == uuid.Nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
		return
	}

	trackID, err := uuid.Parse(c.Param("id")) // Changed to uuid.Parse
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid track id"})
		return
	}

	jobID, err := h.hlsService.TriggerTranscodeQueue(c.Request.Context(), trackID, userID)
	if err != nil {
		if err.Error() == "track not found" {
			c.JSON(http.StatusNotFound, gin.H{"error": "track not found"})
			return
		}
		if err.Error() == "forbidden: user does not own this track" {
			c.JSON(http.StatusForbidden, gin.H{"error": "forbidden"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusAccepted, gin.H{"job_id": jobID})
}
