using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using PARR.Core.Repositories.Interfaces;
using PARR.Core.Repositories.Interfaces.RobotRepositories;
using PARR.Core.Services.Snapshots.Interfaces;
using PARR.Domain.Entities.RobotEntities;
using PARR.Domain.Exceptions;

namespace PARR.Core.Services.Snapshots.Implementations
{
    /// <summary>
    /// Снапшоты для таблицы RobotConfiguration
    /// </summary>
    internal class RobotConfigurationSnapshotService : ISnapshotProvider
    {
        private readonly IRobotConfigurationRepository _robotConfigurationRepository;
        private readonly IRobotConfigurationSnapshotRepository _robotConfigurationSnapshotRepository;
        private readonly ILogger<RobotConfigurationSnapshotService> _logger;
        private readonly ISnapshotSettings _snapshotSettings;

        public TimeSpan Interval => _snapshotSettings.RobotConfigurationSnapshotInterval;// TimeSpan.FromMinutes(2);

        public TimeSpan RetentionPeriod => _snapshotSettings.RobotConfigurationSnapshotRetentionPeriod;//TimeSpan.FromDays(60);

        public RobotConfigurationSnapshotService(
                IRobotConfigurationRepository robotConfigurationRepository,
                IRobotConfigurationSnapshotRepository robotConfigurationSnapshotRepository,
                ILogger<RobotConfigurationSnapshotService> logger,
                ISnapshotSettings snapshotSettings
            )
        {
            _robotConfigurationRepository = robotConfigurationRepository;
            _robotConfigurationSnapshotRepository = robotConfigurationSnapshotRepository;
            _logger = logger;
            _snapshotSettings = snapshotSettings;
        }


        public async Task TakeSnapshotAsync(CancellationToken cancellationToken)
        {
            var now = DateTimeOffset.UtcNow;

            _logger.LogDebug("Сбор метрик для снапшота RobotConfigurations...");

            var stats = await _robotConfigurationRepository.Get()
                .GroupBy(t => new { t.RobotCode, t.RobotStatusCode, t.TaskStatusCode })
                .Select(g => new
                {
                    g.Key.RobotCode,
                    g.Key.RobotStatusCode,
                    g.Key.TaskStatusCode,
                    Count = g.Count()
                })
                .ToListAsync(cancellationToken);

            if (!stats.Any())
            {
                _logger.LogDebug("Нет активных заданий роботов для создания снапшота.");
                return;
            }

            var snapshots = stats.Select(s => new RobotConfigurationSnapshot
            {
                Id = Guid.NewGuid(),
                DateCreated = now,
                RobotCode = s.RobotCode,
                RobotStatusCode = s.RobotStatusCode,
                TaskStatusCode = s.TaskStatusCode,
                Count = s.Count
            }).ToList();

            if (!await _robotConfigurationSnapshotRepository.AddRangeAsync(snapshots) || !await _robotConfigurationSnapshotRepository.CommitAsync())
                throw new DbErrorException("Ошибка при сохранении в БД");

            _logger.LogInformation("Успешно сохранен снапшот RobotConfigurations. Записано строк: {Count}. Периодичность: {Interval}", snapshots.Count, Interval);
        }


        public async Task CleanUpOldSnapshotsAsync(CancellationToken cancellationToken)
        {
            // Вычисляем граничную дату (всё, что было ДО нее — удаляем)
            var thresholdDate = DateTimeOffset.UtcNow.Subtract(RetentionPeriod);

            _logger.LogInformation("[{ServiceName}] Запуск очистки старых снапшотов. Удаление данных старше {ThresholdDate}", GetType().Name, thresholdDate);

            // Фильтруем старые записи и вызываем ExecuteDeleteAsync для удаления прямо в базе данных
            var deletedCount = await _robotConfigurationSnapshotRepository.Get()
                                                .Where(s => s.DateCreated < thresholdDate)
                                                .ExecuteDeleteAsync(cancellationToken);

            _logger.LogInformation("[{ServiceName}] Очистка завершена. Удалено устаревших строк снапшотов: {Count}", GetType().Name, deletedCount);
        }
    }
}
