using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace ZB.MOM.WW.GalaxyRepository;

/// <summary>Background service that periodically refreshes the Galaxy Repository hierarchy cache off the request path.</summary>
public sealed class GalaxyHierarchyRefreshService(
    IGalaxyHierarchyCache cache,
    IOptions<GalaxyRepositoryOptions> options,
    ILogger<GalaxyHierarchyRefreshService> logger,
    TimeProvider? timeProvider = null) : BackgroundService
{
    private readonly TimeProvider _timeProvider = timeProvider ?? TimeProvider.System;

    /// <inheritdoc />
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        TimeSpan interval = TimeSpan.FromSeconds(Math.Max(1, options.Value.DashboardRefreshIntervalSeconds));

        try
        {
            await cache.RefreshAsync(stoppingToken).ConfigureAwait(false);
        }
        catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
        {
            return;
        }
        catch (Exception exception)
        {
            // A transient first-load failure (e.g. a TimeoutException or
            // Win32Exception from connection establishment, or a DbException
            // subtype the cache does not catch) must not fault this
            // BackgroundService and stop the whole host. The cache records
            // its own Unavailable/Stale status; the periodic tick below retries.
            logger.LogWarning(exception, "Initial Galaxy hierarchy cache load failed; will retry on the refresh interval.");
        }

        using PeriodicTimer timer = new(interval, _timeProvider);
        try
        {
            while (await timer.WaitForNextTickAsync(stoppingToken).ConfigureAwait(false))
            {
                try
                {
                    await cache.RefreshAsync(stoppingToken).ConfigureAwait(false);
                }
                catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
                {
                    return;
                }
                catch (Exception exception)
                {
                    logger.LogWarning(exception, "Galaxy hierarchy cache refresh tick failed.");
                }
            }
        }
        catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
        {
        }
    }
}
