using OrderPROPrint.Forms; namespace OrderPROPrint.Services; public class PollingService { private readonly PrintApiClient _apiClient; private readonly PrintService _printService; private readonly string _printerName; private readonly int _intervalSeconds; private readonly Action _onStatusUpdate; private readonly Action _onError; private System.Threading.Timer? _timer; private bool _isProcessing; private int _totalPrinted; private readonly object _lock = new(); public bool IsRunning { get; private set; } public PollingService( PrintApiClient apiClient, PrintService printService, string printerName, int intervalSeconds, Action onStatusUpdate, Action onError) { _apiClient = apiClient; _printService = printService; _printerName = printerName; _intervalSeconds = Math.Max(intervalSeconds, 5); _onStatusUpdate = onStatusUpdate; _onError = onError; } public void Start() { if (IsRunning) return; IsRunning = true; _timer = new System.Threading.Timer( async _ => await PollAsync(), null, TimeSpan.Zero, TimeSpan.FromSeconds(_intervalSeconds) ); _onStatusUpdate($"Aktywne (co {_intervalSeconds}s)"); } public void Stop() { IsRunning = false; _timer?.Change(Timeout.Infinite, Timeout.Infinite); _timer?.Dispose(); _timer = null; } private async Task PollAsync() { lock (_lock) { if (_isProcessing) return; _isProcessing = true; } try { var jobs = await _apiClient.GetPendingJobsAsync(); LogForm.Log($"Polling: znaleziono {jobs.Count} zleceń"); if (jobs.Count == 0) { _onStatusUpdate($"Brak zleceń (wydrukowano: {_totalPrinted})"); return; } int printed = 0; int failed = 0; string lastError = ""; foreach (var job in jobs) { try { LogForm.Log($"Job {job.Id}: pobieranie etykiety..."); var labelBytes = await _apiClient.DownloadLabelAsync(job.Id); LogForm.Log($"Job {job.Id}: pobrano {labelBytes.Length} bajtów"); if (labelBytes.Length == 0) { failed++; lastError = $"Job {job.Id}: pusty plik etykiety"; LogForm.Log($"BŁĄD: {lastError}"); continue; } LogForm.Log($"Job {job.Id}: drukowanie na '{_printerName}'..."); bool success = _printService.PrintPdf(labelBytes, _printerName); if (success) { await _apiClient.MarkCompleteAsync(job.Id); printed++; _totalPrinted++; LogForm.Log($"Job {job.Id}: wydrukowano i oznaczono jako complete ✓"); } else { failed++; lastError = $"Job {job.Id}: druk nie powiódł się"; LogForm.Log($"BŁĄD: {lastError}"); } } catch (HttpRequestException ex) { failed++; lastError = $"Job {job.Id}: HTTP {ex.StatusCode} — {ex.Message}"; LogForm.Log($"BŁĄD: {lastError}"); } catch (Exception ex) { failed++; lastError = $"Job {job.Id}: {ex.GetType().Name} — {ex.Message}"; LogForm.Log($"BŁĄD: {lastError}"); } } if (failed > 0) { _onStatusUpdate($"Wydrukowano: {printed}, błędy: {failed} (łącznie: {_totalPrinted})"); } else { _onStatusUpdate($"Wydrukowano {printed} etykiet (łącznie: {_totalPrinted})"); } } catch (HttpRequestException ex) { _onError($"API niedostępne: {ex.Message}"); } catch (TaskCanceledException) { _onError("Timeout połączenia z API"); } catch (Exception ex) { _onError(ex.Message); } finally { lock (_lock) { _isProcessing = false; } } } }