package handlers

import (
	"context"
	"errors"
	"net/http"

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

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"go.uber.org/zap"
)

// BitrateAdaptationServiceInterface defines methods needed for bitrate handler
type BitrateAdaptationServiceInterface interface {
	AdaptBitrate(ctx context.Context, trackID, userID uuid.UUID, currentBitrate int, bandwidth int64, bufferLevel float64) (int, error)
	GetAnalytics(ctx context.Context, trackID uuid.UUID) (*services.BitrateAnalytics, error)
}

// BitrateHandler gère les requêtes pour l'adaptation de bitrate
// T0349: Create Bitrate Adaptation Endpoint
type BitrateHandler struct {
	adaptationService BitrateAdaptationServiceInterface
	commonHandler     *CommonHandler
}

// NewBitrateHandler crée un nouveau handler de bitrate
func NewBitrateHandler(adaptationService *services.BitrateAdaptationService, logger *zap.Logger) *BitrateHandler {
	return &BitrateHandler{
		adaptationService: adaptationService,
		commonHandler:     NewCommonHandler(logger),
	}
}

// NewBitrateHandlerWithInterface creates a new bitrate handler with interface (for testing)
func NewBitrateHandlerWithInterface(adaptationService BitrateAdaptationServiceInterface, logger *zap.Logger) *BitrateHandler {
	return &BitrateHandler{
		adaptationService: adaptationService,
		commonHandler:     NewCommonHandler(logger),
	}
}

// AdaptBitrateRequest représente la requête pour adapter le bitrate
type AdaptBitrateRequest struct {
	CurrentBitrate int     `json:"current_bitrate" binding:"required" validate:"required"`
	Bandwidth      int64   `json:"bandwidth" binding:"required" validate:"required"`
	BufferLevel    float64 `json:"buffer_level" binding:"required" validate:"required"`
}

// AdaptBitrate gère la requête POST /api/v1/tracks/:id/bitrate/adapt
// Reçoit les métriques de streaming et retourne le bitrate recommandé
func (h *BitrateHandler) AdaptBitrate(c *gin.Context) {
	// Récupérer l'ID de l'utilisateur depuis le contexte (défini par le middleware d'authentification)
	userIDVal, exists := c.Get("user_id")
	if !exists {
		// MOD-P2-003: Utiliser AppError au lieu de gin.H
		RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
		return
	}
	userID, ok := userIDVal.(uuid.UUID)
	if !ok || userID == uuid.Nil {
		// MOD-P2-003: Utiliser AppError au lieu de gin.H
		RespondWithAppError(c, apperrors.NewUnauthorizedError("unauthorized"))
		return
	}

	// Récupérer l'ID du track depuis les paramètres de l'URL
	trackIDStr := c.Param("id")
	trackID, err := uuid.Parse(trackIDStr)
	if err != nil {
		// MOD-P2-003: Utiliser AppError au lieu de gin.H
		RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, "invalid track id"))
		return
	}

	// Valider et parser le body de la requête
	var req AdaptBitrateRequest
	if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
		RespondWithAppError(c, appErr)
		return
	}

	// Appeler le service d'adaptation de bitrate
	newBitrate, err := h.adaptationService.AdaptBitrate(
		c.Request.Context(),
		trackID,
		userID,
		req.CurrentBitrate,
		req.Bandwidth,
		req.BufferLevel,
	)
	if err != nil {
		// Le service retourne des erreurs de validation avec des messages spécifiques
		// On peut distinguer les erreurs de validation des erreurs internes
		if errors.Is(err, services.ErrInvalidTrackID) ||
			errors.Is(err, services.ErrInvalidUserID) ||
			errors.Is(err, services.ErrInvalidBitrate) ||
			errors.Is(err, services.ErrInvalidBufferLevel) {
			// MOD-P2-003: Utiliser AppError au lieu de gin.H
			RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, err.Error()))
			return
		}
		// MOD-P2-003: Utiliser AppError au lieu de gin.H
		RespondWithAppError(c, apperrors.New(apperrors.ErrCodeInternal, err.Error()))
		return
	}

	// Retourner le bitrate recommandé
	// Action 1.3.2.1: Use wrapped format helper
	RespondSuccess(c, http.StatusOK, gin.H{"recommended_bitrate": newBitrate})
}

// GetAnalytics gère la requête GET /api/v1/tracks/:id/bitrate/analytics
// Retourne les statistiques d'adaptation de bitrate pour un track
// T0354: Create Bitrate Adaptation Analytics Endpoint
func (h *BitrateHandler) GetAnalytics(c *gin.Context) {
	// Récupérer l'ID du track depuis les paramètres de l'URL
	trackIDStr := c.Param("id")
	trackID, err := uuid.Parse(trackIDStr)
	if err != nil {
		// MOD-P2-003: Utiliser AppError au lieu de gin.H
		RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, "invalid track id"))
		return
	}

	// Récupérer les analytics depuis le service
	analytics, err := h.adaptationService.GetAnalytics(c.Request.Context(), trackID)
	if err != nil {
		if errors.Is(err, services.ErrInvalidTrackID) {
			// MOD-P2-003: Utiliser AppError au lieu de gin.H
			RespondWithAppError(c, apperrors.New(apperrors.ErrCodeValidation, "invalid track id"))
			return
		}
		// MOD-P2-003: Utiliser AppError au lieu de gin.H
		RespondWithAppError(c, apperrors.New(apperrors.ErrCodeInternal, err.Error()))
		return
	}

	// Retourner les analytics
	// Action 1.3.2.1: Use wrapped format helper
	RespondSuccess(c, http.StatusOK, gin.H{"analytics": analytics})
}
