using System.IO;
using songrequests_blazor.Data;
using System.Collections.Concurrent;
using Microsoft.EntityFrameworkCore;

namespace songrequests_blazor.Services
{
    public class ScanService : IHostedService, IDisposable
    {
        public static BlockingCollection<Library> Queue { get; set; } = new();

        IDbContextFactory<LocalDbContext> _dbContextFactory;

        public ScanService(IDbContextFactory<LocalDbContext> contextFactory)
        {
            _dbContextFactory = contextFactory;
        }

        public static void AddToQueue(Library itm)
        {
            if (itm.ScanPaths == null || itm.ScanPaths.Count == 0) return;
            if (!Queue.Contains(itm)) Queue.Add(itm);
        }

        public void Dispose()
        {
            Queue.Dispose();
        }

        private Timer? timer;

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            await Task.Run(() =>
            {
                timer = new Timer(ScanFiles, cancellationToken, 0, 5000);
            });
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            // BlockingCollection leeren
            await Task.Run(() =>
            {
                while (Queue.TryTake(out _)) { }
            });
        }


        private void ScanFiles(object? state)
        {
            CancellationToken token;
            if (state != null)
            {
                token = (CancellationToken)state;
            }
            else
            {
                token = new CancellationTokenSource().Token;
            }
            while (Queue?.Count > 0)
            {

                Library lib = Queue.Take();
                List<Song> files = new List<Song>();
                foreach (var ScanPath in lib.ScanPaths ?? [])
                {
                    Console.WriteLine($"{DateTime.Now:g} Scanning {ScanPath}");
                    foreach (string file in Directory.GetFiles(ScanPath, "*.mp3", SearchOption.AllDirectories))
                    {
                        if (lib.Songs == null || !lib.Songs.Any(s => s.Uri.Trim().ToLower() == file.Trim().ToLower()))
                        {
                            var song = Song.FromFile(file);
                            song.Library = lib;
                            files.Add(song);
                        }
                    }
                }

                Console.WriteLine($"{DateTime.Now:g} Adding found files to library...");
                using (LocalDbContext db = _dbContextFactory.CreateDbContext())
                {
                    db.Libraries.Update(lib);
                    if (lib.Songs == null) lib.Songs = new();
                    lib.Songs.AddRange(files);
                    db.SaveChanges();
                }
            }
        }
    }
}
