using System; using System.IO; using Электронная_Фармация.Properties; namespace Электронная_Фармация.Classes { /// /// Shared application paths and API settings. /// public static class AppConfig { public const string DefaultApiBaseUrl = "https://24pharmdata.ru"; public const string DefaultUpdateCheckBaseUrl = "https://git.24pharmdata.ru"; public const string DefaultUpdateRepo = "pharmdata/elfisa-pharmacy"; private const string LegacyApiBaseUrl = "http://195.34.241.84:9988"; private const string ApiBaseUrlEnvVar = "ELF_API_BASE_URL"; private static bool _sqliteInteropPrepared; private static readonly object _sqliteInteropLock = new object(); /// /// Replaces known dead API URLs in saved user settings. /// /// /// Carries user settings across AssemblyVersion bumps (new user.config folder). /// public static void UpgradeUserSettingsIfNeeded() { try { if (Settings.Default.UpgradeSettings) { Settings.Default.Upgrade(); Settings.Default.UpgradeSettings = false; Settings.Default.Save(); AppDebugLog.Info("AppConfig", "User settings upgraded from previous version"); } } catch (Exception ex) { AppDebugLog.Info("AppConfig", $"Upgrade settings skipped: {ex.Message}"); } } public static void MigrateLegacySettings() { var current = Settings.Default.ApiBaseUrl; if (string.IsNullOrWhiteSpace(current)) { return; } var normalized = NormalizeApiBaseUrl(current); if (string.Equals(normalized, LegacyApiBaseUrl, StringComparison.OrdinalIgnoreCase) || string.Equals(normalized, "http://195.34.241.84:9988", StringComparison.OrdinalIgnoreCase)) { Settings.Default.ApiBaseUrl = DefaultApiBaseUrl; Settings.Default.stringToken = string.Empty; Settings.Default.Save(); AppDebugLog.Info("AppConfig", $"ApiBaseUrl мигрирован: {LegacyApiBaseUrl} -> {DefaultApiBaseUrl}"); } } public static string ApiBaseUrl { get { var fromSettings = Settings.Default.ApiBaseUrl; if (!string.IsNullOrWhiteSpace(fromSettings)) { return NormalizeApiBaseUrl(fromSettings); } var fromEnv = Environment.GetEnvironmentVariable(ApiBaseUrlEnvVar); if (!string.IsNullOrWhiteSpace(fromEnv)) { return NormalizeApiBaseUrl(fromEnv); } return DefaultApiBaseUrl; } } public static string NormalizeApiBaseUrl(string url) { if (string.IsNullOrWhiteSpace(url)) { return DefaultApiBaseUrl; } url = url.Trim().TrimEnd('/'); if (!url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && !url.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { url = "http://" + url; } return url; } public static string SqliteDbPath { get { var baseDir = AppDomain.CurrentDomain.BaseDirectory; var root = Path.Combine(baseDir, "efClient.db"); var data = Path.Combine(baseDir, "Data", "efClient.db"); if (File.Exists(root)) { return root; } if (File.Exists(data)) { return data; } return root; } } public static string SqliteConnectionString { get { EnsureSQLiteInteropInBaseDir(); return $"Data Source={SqliteDbPath};Version=3;New=False;"; } } public static string LocationId { get { return Settings.Default.LocationId ?? string.Empty; } } public static void SetLocationId(string locationId) { Settings.Default.LocationId = (locationId ?? string.Empty).Trim(); Settings.Default.Save(); } public static string InvoiceExportPath { get { return Settings.Default.InvoiceExportPath ?? string.Empty; } } public static void SetInvoiceExportPath(string path) { Settings.Default.InvoiceExportPath = (path ?? string.Empty).Trim(); Settings.Default.Save(); } /// /// Gitea base URL for forced update checks (no trailing slash). /// public static string UpdateCheckBaseUrl { get { var fromEnv = Environment.GetEnvironmentVariable("ELF_UPDATE_CHECK_BASE_URL"); if (!string.IsNullOrWhiteSpace(fromEnv)) { return NormalizeApiBaseUrl(fromEnv); } var fromSettings = Settings.Default.UpdateCheckBaseUrl; if (!string.IsNullOrWhiteSpace(fromSettings)) { return NormalizeApiBaseUrl(fromSettings); } return DefaultUpdateCheckBaseUrl; } } /// /// owner/repo on Gitea, e.g. pharmdata/elfisa-pharmacy. /// public static string UpdateRepo { get { var fromEnv = Environment.GetEnvironmentVariable("ELF_UPDATE_REPO"); if (!string.IsNullOrWhiteSpace(fromEnv)) { return fromEnv.Trim().Trim('/'); } var fromSettings = Settings.Default.UpdateRepo; if (!string.IsNullOrWhiteSpace(fromSettings)) { return fromSettings.Trim().Trim('/'); } return DefaultUpdateRepo; } } /// /// Optional read-only Gitea token for private release repos. /// public static string UpdateApiToken { get { var fromEnv = Environment.GetEnvironmentVariable("ELF_UPDATE_API_TOKEN"); if (!string.IsNullOrWhiteSpace(fromEnv)) { return fromEnv.Trim(); } return Settings.Default.UpdateApiToken ?? string.Empty; } } private static void EnsureSQLiteInteropInBaseDir() { // System.Data.SQLite ожидает SQLite.Interop.dll рядом с exe. // Важно: разрядность DLL должна совпадать с процессом (Prefer32Bit => x86). if (_sqliteInteropPrepared) { return; } lock (_sqliteInteropLock) { if (_sqliteInteropPrepared) { return; } var baseDir = AppDomain.CurrentDomain.BaseDirectory; var targetDll = Path.Combine(baseDir, "SQLite.Interop.dll"); var archFolder = Environment.Is64BitProcess ? "x64" : "x86"; var sourceDll = Path.Combine(baseDir, archFolder, "SQLite.Interop.dll"); var sourcePdb = Path.Combine(baseDir, archFolder, "SQLite.Interop.pdb"); try { if (File.Exists(sourceDll)) { // Всегда подкладываем DLL нужной разрядности (даже если в корне уже лежит "чужая"). File.Copy(sourceDll, targetDll, overwrite: true); var targetPdb = Path.Combine(baseDir, "SQLite.Interop.pdb"); if (File.Exists(sourcePdb)) { File.Copy(sourcePdb, targetPdb, overwrite: true); } } } catch { // Если копирование не удалось (права/readonly/и т.п.), дальше будет явное исключение от SQLite. } _sqliteInteropPrepared = true; } } } }