using System;
using System.Threading;
using System.Threading.Tasks;
using Knot.Shared.Infrastructure.Persistence;
using Knot.Shared.Infrastructure.Persistence.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace Knot.Shared.Infrastructure.Statistics;

public class StatisticsWorker : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;

    public StatisticsWorker(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                using var scope = _serviceProvider.CreateScope();
                var db = scope.ServiceProvider.GetRequiredService<SystemDbContext>();

                // Simplified gathering for daily stats
                var today = DateTime.UtcNow.Date;
                var stat = await db.DailyStats.FirstOrDefaultAsync(s => s.Date == today, stoppingToken);

                if (stat == null)
                {
                    stat = new DailyStat { Date = today };
                    db.DailyStats.Add(stat);
                }

                var conn = db.Database.GetDbConnection();
                var cmd = conn.CreateCommand();

                stat.ActiveUsers = await cmd.QueryTotalUsersAsync();

                long dbSize = 0;
                long filesSize = 0;
                long mongoSize = 0;
                long messagesCount = 0;
                try
                {
                    // 1. Database size itself
                    cmd.CommandText = "SELECT pg_database_size(current_database());";
                    var dbSizeResult = await cmd.ExecuteScalarAsync();
                    dbSize = dbSizeResult != DBNull.Value ? Convert.ToInt64(dbSizeResult) : 0;

                    var mongoDb = scope.ServiceProvider.GetRequiredService<MongoDB.Driver.IMongoDatabase>();
                    var messagesCol = mongoDb.GetCollection<MongoDB.Bson.BsonDocument>("messages");
                    messagesCount = await messagesCol.CountDocumentsAsync(new MongoDB.Bson.BsonDocument(), cancellationToken: stoppingToken);
                    var statsCmd = new MongoDB.Bson.BsonDocument("dbStats", 1);
                    var mongoStats = await mongoDb.RunCommandAsync<MongoDB.Bson.BsonDocument>(statsCmd, cancellationToken: stoppingToken);
                    if (mongoStats.Contains("dataSize"))
                        mongoSize = mongoStats["dataSize"].ToInt64();

                    var fileStorage = scope.ServiceProvider.GetRequiredService<Knot.Shared.Kernel.Storage.IFileStorageService>();
                    var allMinioFiles = await fileStorage.ListFilesAsync();
                    foreach (var f in allMinioFiles) { filesSize += f.Size; }
                }
                catch { }

                stat.TotalMessages = (int)messagesCount;
                stat.TotalFilesSize = dbSize + mongoSize + filesSize;

                await db.SaveChangesAsync(stoppingToken);
            }
            catch
            {
                // Background service swallows errors to not crash the app
            }

            await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
        }
    }
}
