using Extrudex.Domain.Interfaces;
using Extrudex.Infrastructure.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Extrudex.API.Jobs;

/// <summary>
/// Background service that periodically syncs Moonraker printer status
/// and print job history into the Extrudex database. Runs as a hosted
/// service and polls all active Moonraker printers on a configurable
/// interval to update printer state and map completed print jobs
/// to PrintJob and FilamentUsage entities.
///
/// Configuration is bound from the "MoonrakerPrinterSync" section in
/// appsettings.json. Set Enabled=false to disable without removing
/// the service registration.
/// </summary>
public class MoonrakerPrinterSyncJob : BackgroundService
{
    private readonly IMoonrakerPrinterSyncService _syncService;
    private readonly MoonrakerPrinterSyncOptions _options;
    private readonly ILogger<MoonrakerPrinterSyncJob> _logger;

    /// <summary>
    /// Creates a new MoonrakerPrinterSyncJob.
    /// </summary>
    /// <param name="syncService">The service that performs the actual sync logic.</param>
    /// <param name="options">Configuration options for polling interval and timeouts.</param>
    /// <param name="logger">Logger for diagnostic output.</param>
    public MoonrakerPrinterSyncJob(
        IMoonrakerPrinterSyncService syncService,
        IOptions<MoonrakerPrinterSyncOptions> options,
        ILogger<MoonrakerPrinterSyncJob> logger)
    {
        _syncService = syncService;
        _options = options.Value;
        _logger = logger;
    }

    /// <inheritdoc />
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        if (!_options.Enabled)
        {
            _logger.LogInformation("Moonraker printer sync job is disabled via configuration — exiting");
            return;
        }

        _logger.LogInformation(
            "Moonraker printer sync job starting — polling every {Interval}",
            _options.PollingInterval);

        // Delay briefly on startup to allow the web host to fully initialize
        await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                var syncedCount = await _syncService.SyncAllAsync(stoppingToken);

                _logger.LogInformation(
                    "Moonraker printer sync completed — {SyncedCount} printer(s) synced. Next sync in {Interval}",
                    syncedCount, _options.PollingInterval);
            }
            catch (Exception ex) when (ex is not OperationCanceledException)
            {
                _logger.LogError(ex,
                    "Error during Moonraker printer sync cycle — will retry in {Interval}",
                    _options.PollingInterval);
            }

            await Task.Delay(_options.PollingInterval, stoppingToken);
        }

        _logger.LogInformation("Moonraker printer sync job shutting down");
    }
}