package services

import (
	"context"
	"fmt"

	"veza-backend-api/internal/models"

	"github.com/google/uuid" // Added import for uuid
	"go.uber.org/zap"
	"gorm.io/gorm"
)

// TrackUploadService gère le suivi de progression des uploads de tracks
type TrackUploadService struct {
	db     *gorm.DB
	logger *zap.Logger
}

// NewTrackUploadService crée un nouveau service de suivi d'upload
func NewTrackUploadService(db *gorm.DB, logger *zap.Logger) *TrackUploadService {
	if logger == nil {
		logger = zap.NewNop()
	}
	return &TrackUploadService{
		db:     db,
		logger: logger,
	}
}

// GetUploadProgress récupère la progression d'un upload de track
func (s *TrackUploadService) GetUploadProgress(ctx context.Context, trackID uuid.UUID) (*models.UploadProgress, error) { // Changed trackID to uuid.UUID
	var track models.Track
	if err := s.db.WithContext(ctx).First(&track, "id = ?", trackID).Error; err != nil { // Updated query
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("track not found")
		}
		return nil, fmt.Errorf("failed to get track: %w", err)
	}

	// Calculer le pourcentage de progression basé sur le statut
	progress := s.calculateProgress(track.Status)

	return &models.UploadProgress{
		TrackID:           trackID,
		Status:            track.Status,
		Progress:          progress,
		Message:           track.StatusMessage,
		StreamStatus:      track.StreamStatus,
		StreamManifestURL: track.StreamManifestURL,
	}, nil
}

// UpdateUploadStatus met à jour le statut d'un track
func (s *TrackUploadService) UpdateUploadStatus(ctx context.Context, trackID uuid.UUID, status models.TrackStatus, message string) error { // Changed trackID to uuid.UUID
	updates := map[string]interface{}{
		"status": status,
	}
	if message != "" {
		updates["status_message"] = message
	}

	if err := s.db.WithContext(ctx).Model(&models.Track{}).Where("id = ?", trackID).Updates(updates).Error; err != nil {
		return fmt.Errorf("failed to update status: %w", err)
	}

	s.logger.Info("Track upload status updated",
		zap.Any("track_id", trackID), // Changed to zap.Any for uuid.UUID
		zap.String("status", string(status)),
		zap.String("message", message),
	)

	return nil
}

// calculateProgress calcule le pourcentage de progression basé sur le statut
func (s *TrackUploadService) calculateProgress(status models.TrackStatus) int {
	switch status {
	case models.TrackStatusUploading:
		return 25 // 25% pendant l'upload
	case models.TrackStatusProcessing:
		return 50 // 50% pendant le traitement
	case models.TrackStatusCompleted:
		return 100 // 100% une fois terminé
	case models.TrackStatusFailed:
		return 0 // 0% en cas d'échec
	default:
		return 0
	}
}

// GetUploadStats récupère les statistiques d'upload pour un utilisateur
// BE-API-032: Implement upload stats endpoint
func (s *TrackUploadService) GetUploadStats(ctx context.Context, userID uuid.UUID) (map[string]interface{}, error) {
	stats := map[string]interface{}{
		"total_uploads": int64(0),
		"total_size":    int64(0),
		"audio_files":   int64(0),
		"image_files":   int64(0),
		"video_files":   int64(0),
	}

	// Compter le nombre total d'uploads (tracks) pour l'utilisateur
	var totalUploads int64
	if err := s.db.WithContext(ctx).Model(&models.Track{}).
		Where("creator_id = ?", userID).
		Count(&totalUploads).Error; err != nil {
		return nil, fmt.Errorf("failed to count total uploads: %w", err)
	}
	stats["total_uploads"] = totalUploads

	// Calculer la taille totale des fichiers
	var totalSize int64
	if err := s.db.WithContext(ctx).Model(&models.Track{}).
		Where("creator_id = ?", userID).
		Select("COALESCE(SUM(file_size), 0)").
		Scan(&totalSize).Error; err != nil {
		return nil, fmt.Errorf("failed to calculate total size: %w", err)
	}
	stats["total_size"] = totalSize

	// Compter les fichiers audio (mp3, flac, wav, etc.)
	var audioFiles int64
	if err := s.db.WithContext(ctx).Model(&models.Track{}).
		Where("creator_id = ? AND format IN (?)", userID, []string{"mp3", "flac", "wav", "aac", "ogg", "m4a"}).
		Count(&audioFiles).Error; err != nil {
		return nil, fmt.Errorf("failed to count audio files: %w", err)
	}
	stats["audio_files"] = audioFiles

	// Compter les fichiers image (jpg, png, gif, etc.)
	// Note: Les images sont généralement dans cover_art_path, mais on peut aussi chercher dans les tracks
	// Pour l'instant, on se concentre sur les tracks audio
	var imageFiles int64
	if err := s.db.WithContext(ctx).Model(&models.Track{}).
		Where("creator_id = ? AND format IN (?)", userID, []string{"jpg", "jpeg", "png", "gif", "webp"}).
		Count(&imageFiles).Error; err != nil {
		// Si la requête échoue (format non supporté pour images), on laisse à 0
		s.logger.Debug("Image files count query failed, setting to 0", zap.Error(err))
	}
	stats["image_files"] = imageFiles

	// Compter les fichiers vidéo (mp4, avi, etc.)
	var videoFiles int64
	if err := s.db.WithContext(ctx).Model(&models.Track{}).
		Where("creator_id = ? AND format IN (?)", userID, []string{"mp4", "avi", "mov", "mkv", "webm"}).
		Count(&videoFiles).Error; err != nil {
		// Si la requête échoue (format non supporté pour vidéos), on laisse à 0
		s.logger.Debug("Video files count query failed, setting to 0", zap.Error(err))
	}
	stats["video_files"] = videoFiles

	return stats, nil
}
