package services

import (
	"context"
	"fmt"

	"veza-backend-api/internal/database"

	"go.uber.org/zap"
)

// SearchService handles search operations
type SearchService struct {
	db     *database.Database
	logger *zap.Logger
}

// SearchResult represents search results
type SearchResult struct {
	Tracks    []TrackResult    `json:"tracks"`
	Users     []UserResult     `json:"users"`
	Playlists []PlaylistResult `json:"playlists"`
}

type TrackResult struct {
	ID     string `json:"id"`
	Title  string `json:"title"`
	Artist string `json:"artist"`
	URL    string `json:"url"`
}

type UserResult struct {
	ID       string `json:"id"`
	Username string `json:"username"`
	Avatar   string `json:"avatar"`
}

type PlaylistResult struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Cover string `json:"cover"`
}

// NewSearchService creates a new search service
func NewSearchService(db *database.Database, logger *zap.Logger) *SearchService {
	return &SearchService{
		db:     db,
		logger: logger,
	}
}

// Search performs a full-text search
func (ss *SearchService) Search(query string, types []string) (*SearchResult, error) {
	ctx := context.Background()
	results := &SearchResult{}

	// Build search types - if empty, search all
	searchAll := len(types) == 0
	searchTracks := searchAll || contains(types, "track")
	searchUsers := searchAll || contains(types, "user")
	searchPlaylists := searchAll || contains(types, "playlist")

	// Search tracks
	if searchTracks {
		rows, err := ss.db.QueryContext(ctx, `
			SELECT id, title, artist, url
			FROM tracks
			WHERE title ILIKE $1 OR artist ILIKE $1
			LIMIT 10
		`, "%"+query+"%")
		if err != nil {
			return nil, fmt.Errorf("failed to search tracks: %w", err)
		}
		defer rows.Close()

		for rows.Next() {
			var track TrackResult
			if err := rows.Scan(&track.ID, &track.Title, &track.Artist, &track.URL); err != nil {
				continue
			}
			results.Tracks = append(results.Tracks, track)
		}
	}

	// Search users
	if searchUsers {
		rows, err := ss.db.QueryContext(ctx, `
			SELECT id, username, avatar
			FROM users
			WHERE username ILIKE $1
			LIMIT 10
		`, "%"+query+"%")
		if err != nil {
			return nil, fmt.Errorf("failed to search users: %w", err)
		}
		defer rows.Close()

		for rows.Next() {
			var user UserResult
			if err := rows.Scan(&user.ID, &user.Username, &user.Avatar); err != nil {
				continue
			}
			results.Users = append(results.Users, user)
		}
	}

	// Search playlists
	if searchPlaylists {
		rows, err := ss.db.QueryContext(ctx, `
			SELECT id, name, cover_image_url
			FROM playlists
			WHERE name ILIKE $1 AND is_public = TRUE
			LIMIT 10
		`, "%"+query+"%")
		if err != nil {
			return nil, fmt.Errorf("failed to search playlists: %w", err)
		}
		defer rows.Close()

		for rows.Next() {
			var playlist PlaylistResult
			if err := rows.Scan(&playlist.ID, &playlist.Name, &playlist.Cover); err != nil {
				continue
			}
			results.Playlists = append(results.Playlists, playlist)
		}
	}

	return results, nil
}

func contains(slice []string, item string) bool {
	for _, s := range slice {
		if s == item {
			return true
		}
	}
	return false
}
