// // Licensed to the .NET Foundation under one or more agreements.
// // The .NET Foundation licenses this file to you under the MIT license.
//
// using System;
// using System.Collections.Concurrent;
// using System.Collections.Generic;
// using System.Linq;
// using System.Threading;
// using System.Threading.Tasks;
// using FloraMultiPlatformFrontend.Application.Services.Interfaces;
// using FloraMultiPlatformFrontend.Data.Repositories.Interfaces;
// using FloraMultiPlatformFrontend.Presentation.Models.Diagnosis;
// using Microsoft.EntityFrameworkCore;
// using Microsoft.Extensions.Logging;
//
// namespace FloraMultiPlatformFrontend.Data.Repositories;
//
// public class ReleaseDataRepository : IReleaseDataRepository, IDisposable
// {
//     private readonly IDbContextFactory<FloraDbContext> _contextFactory;
//     private readonly ILogger<ReleaseDataRepository> _logger;
//     private readonly IConfigurationService _configurationService;
//     private readonly IRefreshIntervalProvider _refreshIntervalProvider;
//     private readonly Timer _cacheRefreshTimer;
//     private readonly ConcurrentDictionary<int, ReleaseData> _releaseCache = new();
//     private readonly SemaphoreSlim _cacheLock = new(1, 1);
//     private string? _currentMachineCode;
//
//     public ReleaseDataRepository(
//         IDbContextFactory<FloraDbContext> contextFactory,
//         IConfigurationService configurationService,
//         IRefreshIntervalProvider refreshIntervalProvider,
//         ILogger<ReleaseDataRepository> logger
//     )
//     {
//         _contextFactory = contextFactory ?? throw new ArgumentNullException(nameof(contextFactory));
//         _configurationService = configurationService ?? throw new ArgumentNullException(nameof(configurationService));
//         _refreshIntervalProvider = refreshIntervalProvider ?? throw new ArgumentNullException(nameof(refreshIntervalProvider));
//         _logger = logger ?? throw new ArgumentNullException(nameof(logger));
//
//         _cacheRefreshTimer = new Timer(RefreshCache, null, TimeSpan.Zero, _refreshIntervalProvider.DiagnosisInterval);
//         _configurationService.SelectedMachineChanged += OnSelectedMachineChanged;
//         _ = InitializeCacheAsync();
//     }
//
//     private async void OnSelectedMachineChanged(object? sender, EventArgs e)
//     {
//         await InitializeCacheAsync();
//     }
//
//     private async Task InitializeCacheAsync()
//     {
//         var machine = await _configurationService.GetSelectedMachineAsync();
//         var newMachineCode = machine?.Code;
//
//         if (_currentMachineCode != newMachineCode)
//         {
//             _logger.LogInformation("Machine code changed from {OldMachineCode} to {NewMachineCode}. Resetting release data cache.", _currentMachineCode, newMachineCode);
//             _currentMachineCode = newMachineCode;
//             _releaseCache.Clear();
//             _cacheRefreshTimer.Change(TimeSpan.Zero, _refreshIntervalProvider.DiagnosisInterval);
//         }
//     }
//
//     private async void RefreshCache(object? state)
//     {
//         if (string.IsNullOrEmpty(_currentMachineCode))
//         {
//             _logger.LogWarning("Skipping release data cache refresh because machine code is not set.");
//             return;
//         }
//
//         if (!await _cacheLock.WaitAsync(TimeSpan.FromSeconds(1)))
//         {
//             _logger.LogWarning("Could not acquire cache lock to refresh release data. Skipping this cycle.");
//             return;
//         }
//
//         try
//         {
//             _logger.LogDebug("Starting release data cache refresh for machine {MachineCode}", _currentMachineCode);
//             var serverName = await _configurationService.GetMachineServerNameAsync();
//             var tableName = $"{serverName}_{_currentMachineCode}_Release_TBM";
//             var query = $@"
//                 SELECT TagID, TagValue, CAST(Ring AS NVARCHAR(MAX)) AS Ring, CAST(ReleaseOff AS NVARCHAR(MAX)) AS ReleaseOff, CAST(ReleaseOn AS NVARCHAR(MAX)) AS ReleaseOn, CAST(Duration AS NVARCHAR(MAX)) AS Duration
//                 FROM [{tableName}]";
//
//             using var context = await _contextFactory.CreateDbContextAsync();
//             var rawData = await context.Database.SqlQueryRaw<RawReleaseData>(query).ToListAsync();
//
//             foreach (var d in rawData)
//             {
//                 if (_releaseCache.TryGetValue(d.TagID, out var existing))
//                 {
//                     existing.TagValue = d.TagValue == true ? 1 : 0;
//                     existing.Ring = int.TryParse(d.Ring, out var ring) ? ring : 0;
//                     existing.ReleaseOff = DateTime.TryParse(d.ReleaseOff, out var releaseOff) ? releaseOff : null;
//                     existing.ReleaseOn = DateTime.TryParse(d.ReleaseOn, out var releaseOn) ? releaseOn : null;
//                     existing.Duration = d.Duration ?? "...";
//                 }
//                 else
//                 {
//                     _releaseCache[d.TagID] = MapToReleaseData(d);
//                 }
//             }
//             _logger.LogInformation("Release data cache refreshed with {Count} items for machine {MachineCode}", _releaseCache.Count, _currentMachineCode);
//         }
//         catch (Exception ex)
//         {
//             _logger.LogError(ex, "Error refreshing release data cache for machine {MachineCode}", _currentMachineCode);
//         }
//         finally
//         {
//             _cacheLock.Release();
//         }
//     }
//
//     public Task<IEnumerable<ReleaseData>> GetReleaseDataAsync(
//         IEnumerable<int> tagIds,
//         string machineCode,
//         CancellationToken cancellationToken = default
//     )
//     {
//         // if (_currentMachineCode != machineCode)
//         // {
//         //     _logger.LogWarning("Requested machine code {RequestedMachineCode} does not match current machine code {CurrentMachineCode}. Returning empty list.", machineCode, _currentMachineCode);
//         //     return Task.FromResult(Enumerable.Empty<ReleaseData>());
//         // }
//
//         var idList = tagIds.ToList();
//         var results = new List<ReleaseData>(idList.Count);
//         foreach (var id in idList)
//         {
//             if (_releaseCache.TryGetValue(id, out var releaseData))
//             {
//                 results.Add(releaseData);
//             }
//         }
//         return Task.FromResult<IEnumerable<ReleaseData>>(results);
//     }
//
//     public Task<ReleaseData?> GetReleaseDataByTagIdAsync(
//         int tagId,
//         string machineCode,
//         CancellationToken cancellationToken = default
//     )
//     {
//         if (_currentMachineCode != machineCode)
//         {
//             _logger.LogWarning("Requested machine code {RequestedMachineCode} does not match current machine code {CurrentMachineCode}. Returning null.", machineCode, _currentMachineCode);
//             return Task.FromResult<ReleaseData?>(null);
//         }
//
//         _releaseCache.TryGetValue(tagId, out var releaseData);
//         return Task.FromResult(releaseData);
//     }
//
//     public Task<IEnumerable<ReleaseData>> GetAllReleaseDataAsync(
//         string machineCode,
//         CancellationToken cancellationToken = default
//     )
//     {
//         // if (_currentMachineCode != machineCode)
//         // {
//         //     _logger.LogWarning("Requested machine code {RequestedMachineCode} does not match current machine code {CurrentMachineCode}. Returning empty list.", machineCode, _currentMachineCode);
//         //     return Task.FromResult(Enumerable.Empty<ReleaseData>());
//         // }
//
//         return Task.FromResult<IEnumerable<ReleaseData>>(_releaseCache.Values);
//     }
//
//     public Task ResetReleaseFlagsAsync()
//     {
//         foreach ( var releaseData in _releaseCache.Values)
//         {
//             releaseData.WasInactive = false;
//         }
//
//         return Task.CompletedTask;
//     }
//
//     private static ReleaseData MapToReleaseData(RawReleaseData rawData)
//     {
//         return new ReleaseData
//         {
//             TagID = rawData.TagID,
//             TagValue = rawData.TagValue == true ? 1 : 0,
//             Ring = int.TryParse(rawData.Ring, out var ring) ? ring : 0,
//             ReleaseOff = DateTime.TryParse(rawData.ReleaseOff, out var releaseOff) ? releaseOff : null,
//             ReleaseOn = DateTime.TryParse(rawData.ReleaseOn, out var releaseOn) ? releaseOn : null,
//             Duration = rawData.Duration ?? "..."
//         };
//     }
//
//     public void Dispose()
//     {
//         _cacheRefreshTimer?.Dispose();
//         _configurationService.SelectedMachineChanged -= OnSelectedMachineChanged;
//         _cacheLock?.Dispose();
//     }
//
//     /// <summary>
//     /// Raw data class for mapping SQL query results.
//     /// </summary>
//     public class RawReleaseData
//     {
//         public int TagID { get; set; }
//         public bool? TagValue { get; set; }
//         public string? Ring { get; set; }
//         public string? ReleaseOff { get; set; }
//         public string? ReleaseOn { get; set; }
//         public string? Duration { get; set; }
//     }
// }
