using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using UtopiaCanteenSystem.Services;
namespace UtopiaCanteenSystem.ViewModels;
///
/// ViewModel for SettingsView: editable API endpoint (UIND sync URL), save, load from config.
///
public partial class SettingsViewModel : ObservableObject
{
private readonly IConfigService _configService;
private readonly INavigationService _navigation;
private readonly IAdminAuditService _adminAudit;
private readonly ISyncService _syncService;
[ObservableProperty]
private string _syncApiEndpoint = string.Empty;
[ObservableProperty]
private string _scanIntervalDays = "0";
[ObservableProperty]
private string _scanIntervalHours = "0";
[ObservableProperty]
private string _scanIntervalMinutes = "1";
[ObservableProperty]
private string _scanIntervalSeconds = "0";
[ObservableProperty]
private string _adminCardId = "ADMIN";
[ObservableProperty]
private string _saveMessage = string.Empty;
[ObservableProperty]
private bool _isError;
[ObservableProperty]
private bool _isSaving;
[ObservableProperty]
private bool _isPosting;
public bool CanPostNow => !IsPosting;
public string PostButtonText => IsPosting ? "Posting..." : "Post Data";
partial void OnIsPostingChanged(bool value)
{
OnPropertyChanged(nameof(PostButtonText));
OnPropertyChanged(nameof(CanPostNow));
}
public SettingsViewModel(
IConfigService configService,
INavigationService navigation,
IAdminAuditService adminAudit,
ISyncService syncService)
{
_configService = configService;
_navigation = navigation;
_adminAudit = adminAudit;
_syncService = syncService;
LoadFromConfig();
}
/// Loads config from service.
public void LoadFromConfig()
{
SyncApiEndpoint = _configService.GetSyncApiEndpoint();
ScanIntervalDays = _configService.GetScanIntervalDays().ToString();
ScanIntervalHours = _configService.GetScanIntervalHours().ToString();
ScanIntervalMinutes = _configService.GetScanIntervalMinutes().ToString();
ScanIntervalSeconds = _configService.GetScanIntervalSeconds().ToString();
// Always prefer the latest admin login from the database.
var last = _adminAudit.GetLastLogin();
if (last != null && !string.IsNullOrWhiteSpace(last.EmployeeId))
AdminCardId = last.EmployeeId;
else
AdminCardId = "ADMIN";
}
[RelayCommand]
private void Save()
{
IsSaving = true;
if (!int.TryParse(ScanIntervalDays, out var days) || days < 0 || days > 365)
{
SaveMessage = "Scan interval Days must be 0–365.";
IsError = true;
IsSaving = false;
return;
}
if (!int.TryParse(ScanIntervalHours, out var hours) || hours < 0 || hours > 23)
{
SaveMessage = "Scan interval Hours must be 0–23.";
IsError = true;
IsSaving = false;
return;
}
if (!int.TryParse(ScanIntervalMinutes, out var minutes) || minutes < 0 || minutes > 59)
{
SaveMessage = "Scan interval Minutes must be 0–59.";
IsError = true;
IsSaving = false;
return;
}
if (!int.TryParse(ScanIntervalSeconds, out var seconds) || seconds < 0 || seconds > 59)
{
SaveMessage = "Scan interval Seconds must be 0–59.";
IsError = true;
IsSaving = false;
return;
}
if (days == 0 && hours == 0 && minutes == 0 && seconds == 0)
{
SaveMessage = "Scan interval cannot be zero. Use at least 1 second.";
IsError = true;
IsSaving = false;
return;
}
_configService.SetSyncApiEndpoint(SyncApiEndpoint?.Trim() ?? string.Empty);
_configService.SetScanIntervalDays(days);
_configService.SetScanIntervalHours(hours);
_configService.SetScanIntervalMinutes(minutes);
_configService.SetScanIntervalSeconds(seconds);
_configService.SetAdminCardId(AdminCardId?.Trim() ?? string.Empty);
SaveMessage = "Settings saved.";
IsError = false;
IsSaving = false;
}
[RelayCommand]
private void Back()
{
_navigation.NavigateBackFromSettings(GetDashboardTimeout());
}
/// Opens Meal Schedules admin screen (Phase 2.5).
[RelayCommand]
private void OpenMealSchedules()
{
_navigation.NavigateToMealSchedules();
}
[RelayCommand]
private async Task PostDataNow()
{
if (IsPosting)
return;
SaveMessage = string.Empty;
IsError = false;
IsPosting = true;
try
{
// If not configured, do not attempt sync.
if (string.IsNullOrWhiteSpace(_configService.GetMySqlConnectionString()))
{
SaveMessage = "MySQL connection string not configured.";
IsError = true;
return;
}
await _syncService.SyncNowAsync().ConfigureAwait(false);
SaveMessage = "Posted data to production.";
IsError = false;
}
catch
{
SaveMessage = "Failed to post data to production.";
IsError = true;
}
finally
{
IsPosting = false;
}
}
private TimeSpan GetDashboardTimeout() => _configService.GetScanInterval();
}