using System.Windows; using Microsoft.EntityFrameworkCore; using UtopiaCanteenSystem.Data; using UtopiaCanteenSystem.Services; using UtopiaCanteenSystem.ViewModels; namespace UtopiaCanteenSystem; /// /// Application entry point. Initializes database, builds service graph, starts hourly sync timer. /// public partial class App : Application { private System.Timers.Timer? _syncTimer; protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); // Build services (simple composition; no DI container) var dbFactory = new DbContextFactory(); // Auto-create SQLite database on first run using (var db = dbFactory.CreateDbContext()) { db.EnsureDatabaseCreated(); } var configService = new ConfigService(); var rfidService = new RfidService(dbFactory, configService); var syncService = new SyncService(dbFactory, configService); var session = new AppSession(); var authenticationUrl = "https://portal.utopiaindustries.pk/uind/rest/auth/user/"; var authService = new AuthService(authenticationUrl); // NavigationService: declare first so lambdas can capture it, then assign (avoids "used before declared") NavigationService navigationService = null!; navigationService = new NavigationService( session, () => new AdminLoginViewModel(authService, session, navigationService), () => new ScannerViewModel(rfidService, navigationService, session), () => new MainDashboardViewModel(navigationService, rfidService, configService, session), () => new AdminSettingsAuthViewModel(authService, session, navigationService), () => new SettingsViewModel(configService, navigationService)); var mainViewModel = new MainViewModel(navigationService); var mainWindow = new MainWindow { DataContext = mainViewModel }; mainWindow.Show(); // Hourly background sync: every 1 hour, POST unsynced ScanRecords to API _syncTimer = new System.Timers.Timer(TimeSpan.FromHours(1).TotalMilliseconds); _syncTimer.Elapsed += async (_, _) => { try { await syncService.SyncNowAsync().ConfigureAwait(false); } catch { // Ignore; will retry next hour } }; _syncTimer.Start(); } protected override void OnExit(ExitEventArgs e) { _syncTimer?.Stop(); _syncTimer?.Dispose(); base.OnExit(e); } }