package repositories

import (
	"context"

	"github.com/google/uuid"
	"veza-backend-api/internal/models"

	"gorm.io/gorm"
)

// PlaylistVersionRepository définit l'interface pour les opérations sur les versions de playlists
// T0509: Create Playlist Version History
type PlaylistVersionRepository interface {
	// Create crée une nouvelle version
	Create(ctx context.Context, version *models.PlaylistVersion) error

	// GetByID récupère une version par son ID
	GetByID(ctx context.Context, id uuid.UUID) (*models.PlaylistVersion, error)

	// GetByPlaylistID récupère toutes les versions d'une playlist
	GetByPlaylistID(ctx context.Context, playlistID uuid.UUID, limit, offset int) ([]*models.PlaylistVersion, int64, error)

	// GetLatestVersion récupère la dernière version d'une playlist
	GetLatestVersion(ctx context.Context, playlistID uuid.UUID) (*models.PlaylistVersion, error)

	// GetByVersion récupère une version spécifique d'une playlist
	GetByVersion(ctx context.Context, playlistID uuid.UUID, version int) (*models.PlaylistVersion, error)

	// GetNextVersionNumber retourne le prochain numéro de version pour une playlist
	GetNextVersionNumber(ctx context.Context, playlistID uuid.UUID) (int, error)
}

// playlistVersionRepository implémente PlaylistVersionRepository avec GORM
type playlistVersionRepository struct {
	db *gorm.DB
}

// NewPlaylistVersionRepository crée une nouvelle instance de PlaylistVersionRepository
func NewPlaylistVersionRepository(db *gorm.DB) PlaylistVersionRepository {
	return &playlistVersionRepository{
		db: db,
	}
}

// Create crée une nouvelle version
func (r *playlistVersionRepository) Create(ctx context.Context, version *models.PlaylistVersion) error {
	return r.db.WithContext(ctx).Create(version).Error
}

// GetByID récupère une version par son ID
func (r *playlistVersionRepository) GetByID(ctx context.Context, id uuid.UUID) (*models.PlaylistVersion, error) {
	var version models.PlaylistVersion
	if err := r.db.WithContext(ctx).
		Preload("User").
		First(&version, "id = ?", id).Error; err != nil {
		return nil, err
	}
	return &version, nil
}

// GetByPlaylistID récupère toutes les versions d'une playlist
func (r *playlistVersionRepository) GetByPlaylistID(ctx context.Context, playlistID uuid.UUID, limit, offset int) ([]*models.PlaylistVersion, int64, error) {
	var versions []*models.PlaylistVersion
	var total int64

	query := r.db.WithContext(ctx).Model(&models.PlaylistVersion{}).Where("playlist_id = ?", playlistID)

	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	if err := query.
		Preload("User").
		Order("created_at DESC").
		Limit(limit).
		Offset(offset).
		Find(&versions).Error; err != nil {
		return nil, 0, err
	}

	return versions, total, nil
}

// GetLatestVersion récupère la dernière version d'une playlist
func (r *playlistVersionRepository) GetLatestVersion(ctx context.Context, playlistID uuid.UUID) (*models.PlaylistVersion, error) {
	var version models.PlaylistVersion
	if err := r.db.WithContext(ctx).
		Where("playlist_id = ?", playlistID).
		Preload("User").
		Order("version DESC").
		First(&version).Error; err != nil {
		return nil, err
	}
	return &version, nil
}

// GetByVersion récupère une version spécifique d'une playlist
func (r *playlistVersionRepository) GetByVersion(ctx context.Context, playlistID uuid.UUID, version int) (*models.PlaylistVersion, error) {
	var v models.PlaylistVersion
	if err := r.db.WithContext(ctx).
		Where("playlist_id = ? AND version = ?", playlistID, version).
		Preload("User").
		First(&v).Error; err != nil {
		return nil, err
	}
	return &v, nil
}

// GetNextVersionNumber retourne le prochain numéro de version pour une playlist
func (r *playlistVersionRepository) GetNextVersionNumber(ctx context.Context, playlistID uuid.UUID) (int, error) {
	var maxVersion int
	err := r.db.WithContext(ctx).
		Model(&models.PlaylistVersion{}).
		Where("playlist_id = ?", playlistID).
		Select("COALESCE(MAX(version), 0)").
		Scan(&maxVersion).Error

	if err != nil {
		return 0, err
	}

	return maxVersion + 1, nil
}
