package services

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/dhowden/tag"
	"go.uber.org/zap"
)

// AudioMetadata represents extracted audio metadata
type AudioMetadata struct {
	Title    string
	Artist   string
	Album    string
	Genre    string
	Year     int
	Track    int
	Duration float64 // in seconds
	Bitrate  int
	Format   string
}

// MetadataService extracts metadata from audio files
type MetadataService struct {
	logger *zap.Logger
}

// NewMetadataService creates a new metadata service
func NewMetadataService(logger *zap.Logger) *MetadataService {
	return &MetadataService{
		logger: logger,
	}
}

// ExtractMetadata extracts metadata from an audio file
func (ms *MetadataService) ExtractMetadata(filePath string) (*AudioMetadata, error) {
	// Open file
	file, err := os.Open(filePath)
	if err != nil {
		return nil, fmt.Errorf("failed to open file for metadata extraction: %w", err)
	}
	defer file.Close()

	// Read metadata from file
	metadata, err := tag.ReadFrom(file)
	if err != nil {
		// If metadata can't be read, return default metadata
		ms.logger.Warn("Failed to extract metadata, using defaults",
			zap.Error(err),
			zap.String("file_path", filePath),
		)
		return ms.getDefaultMetadata(filePath), nil
	}

	// Extract metadata
	trackNum, _ := metadata.Track()
	result := &AudioMetadata{
		Title:  metadata.Title(),
		Artist: metadata.Artist(),
		Album:  metadata.Album(),
		Genre:  metadata.Genre(),
		Year:   metadata.Year(),
		Track:  trackNum,
		Format: filepath.Ext(filePath),
	}

	// Duration and bitrate would typically be extracted using ffprobe or similar
	// For now, we'll leave these as 0

	return result, nil
}

// getDefaultMetadata returns default metadata based on filename
func (ms *MetadataService) getDefaultMetadata(filePath string) *AudioMetadata {
	filename := filepath.Base(filePath)
	ext := filepath.Ext(filename)
	baseName := filename[:len(filename)-len(ext)]

	// Try to parse "Artist - Title" pattern
	var artist, title string
	if len(baseName) > 3 && baseName[2:4] == " - " {
		parts := baseName[:3] // This won't work, need proper parsing
		artist = string(parts)
		title = baseName[3:]
	} else {
		title = baseName
		artist = "Unknown"
	}

	return &AudioMetadata{
		Title:  title,
		Artist: artist,
		Album:  "",
		Genre:  "",
		Year:   0,
		Track:  0,
		Format: ext,
	}
}

// ValidateMetadata validates extracted metadata
func (ms *MetadataService) ValidateMetadata(metadata *AudioMetadata) error {
	if metadata.Title == "" {
		return fmt.Errorf("title is required")
	}
	if metadata.Artist == "" {
		return fmt.Errorf("artist is required")
	}
	return nil
}
