package services

import (
	"context"
	"errors"
	"fmt"

	"github.com/google/uuid" // Added import for uuid
	"go.uber.org/zap"
	"gorm.io/gorm"
	"veza-backend-api/internal/models"
)

// PlaylistAnalyticsService gère les analytics de playlists
// T0491: Create Playlist Analytics Backend
type PlaylistAnalyticsService struct {
	db     *gorm.DB
	logger *zap.Logger
}

// NewPlaylistAnalyticsService crée un nouveau service d'analytics de playlists
func NewPlaylistAnalyticsService(db *gorm.DB, logger *zap.Logger) *PlaylistAnalyticsService {
	if logger == nil {
		logger = zap.NewNop()
	}
	return &PlaylistAnalyticsService{
		db:     db,
		logger: logger,
	}
}

// PlaylistStats représente les statistiques d'une playlist
type PlaylistStats struct {
	Plays      int64 `json:"plays"`       // Nombre total de lectures (somme des plays des tracks)
	Shares     int64 `json:"shares"`      // Nombre de liens de partage créés
	Likes      int64 `json:"likes"`       // Nombre de follows (équivalent aux likes)
	Followers  int64 `json:"followers"`   // Nombre de followers (déjà dans Playlist.FollowerCount)
	TrackCount int   `json:"track_count"` // Nombre de tracks dans la playlist
}

// GetPlaylistStats récupère les statistiques d'une playlist
func (s *PlaylistAnalyticsService) GetPlaylistStats(ctx context.Context, playlistID uuid.UUID) (*PlaylistStats, error) { // Changed playlistID to uuid.UUID
	// Vérifier que la playlist existe
	var playlist models.Playlist
	if err := s.db.WithContext(ctx).First(&playlist, "id = ?", playlistID).Error; err != nil { // Updated query
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("playlist not found")
		}
		return nil, fmt.Errorf("failed to get playlist: %w", err)
	}

	var stats PlaylistStats

	// Track count (déjà dans le modèle)
	stats.TrackCount = playlist.TrackCount

	// Followers count (déjà dans le modèle)
	stats.Followers = int64(playlist.FollowerCount)

	// Count shares (nombre de liens de partage créés, non supprimés)
	if err := s.db.WithContext(ctx).Model(&models.PlaylistShareLink{}).
		Where("playlist_id = ? AND deleted_at IS NULL", playlistID).
		Count(&stats.Shares).Error; err != nil {
		return nil, fmt.Errorf("failed to count shares: %w", err)
	}

	// Count likes (nombre de follows, non supprimés)
	if err := s.db.WithContext(ctx).Model(&models.PlaylistFollow{}).
		Where("playlist_id = ? AND deleted_at IS NULL", playlistID).
		Count(&stats.Likes).Error; err != nil {
		return nil, fmt.Errorf("failed to count likes: %w", err)
	}

	// Count plays: somme des plays de tous les tracks dans la playlist
	// On compte les TrackPlay pour tous les tracks de la playlist
	type PlayCountResult struct {
		TotalPlays int64
	}
	var playCountResult PlayCountResult

	// Récupérer tous les track IDs de la playlist
	var trackIDs []uuid.UUID // Changed to []uuid.UUID
	if err := s.db.WithContext(ctx).Model(&models.PlaylistTrack{}).
		Where("playlist_id = ?", playlistID).
		Pluck("track_id", &trackIDs).Error; err != nil {
		return nil, fmt.Errorf("failed to get playlist tracks: %w", err)
	}

	// Si la playlist a des tracks, compter les plays
	if len(trackIDs) > 0 {
		if err := s.db.WithContext(ctx).Model(&models.TrackPlay{}).
			Where("track_id IN ?", trackIDs).
			Count(&playCountResult.TotalPlays).Error; err != nil {
			return nil, fmt.Errorf("failed to count plays: %w", err)
		}
	}

	stats.Plays = playCountResult.TotalPlays

	s.logger.Debug("Playlist stats retrieved",
		zap.Any("playlist_id", playlistID), // Changed to zap.Any for uuid.UUID
		zap.Int64("plays", stats.Plays),
		zap.Int64("shares", stats.Shares),
		zap.Int64("likes", stats.Likes),
		zap.Int64("followers", stats.Followers),
	)

	return &stats, nil
}

// IncrementPlaylistPlays incrémente le compteur de plays d'une playlist
// Cette méthode peut être appelée lorsqu'un track de la playlist est joué
func (s *PlaylistAnalyticsService) IncrementPlaylistPlays(ctx context.Context, playlistID uuid.UUID) error { // Changed playlistID to uuid.UUID
	// Note: Pour l'instant, on ne stocke pas de compteur de plays dans Playlist
	// car on le calcule dynamiquement à partir des TrackPlay
	// Cette méthode est prévue pour une future optimisation avec cache
	s.logger.Debug("Playlist play incremented",
		zap.Any("playlist_id", playlistID), // Changed to zap.Any for uuid.UUID
	)
	return nil
}
