using BeWo.Data.Access; using BeWo.Data.Entities; using BeWo.Service.Attributes; using BeWo.Service.Core; using BeWo.Service.ServiceContracts.Enhanced; using BS.Shared.DataContracts; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; using System.Threading.Tasks; namespace BeWo.Service.ServiceImplementations.Enhanced { [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)] public class StatusServiceImp : IStatusService { private readonly List RequiredWebConfigs = new List() { WebConfigSetting.OllamaUrl, WebConfigSetting.Ollama2Url, //WebConfigSetting.XRechnungApiUrl, //WebConfigSetting.StoredFilesFolderPath, //WebConfigSetting.StoredTenantFilesFolderPath, //WebConfigSetting.HelloWorldPdfLocation, //WebConfigSetting.BeWoPlanerServiceRoot, WebConfigSetting.AiPromptsUrl }; private readonly List RequiredWebSecretConfigs = new List() { WebSecretConfigSetting.Ollama2Key, WebSecretConfigSetting.AppStatusApiKey }; public ServerStatusDC GetStatus() { var result = new ServerStatusDC { ServerTime = DateTime.Now.ToString("o"), Version = Assembly.GetExecutingAssembly() .GetName().Version?.ToString() ?? "unbekannt", Services = new List() }; // Datenbankverbindung prüfen result.DatabaseOk = executeCheck("Datenbank", CheckDatabase); // Einzelne Subsysteme prüfen result.Services.Add(executeCheck("AIModule", CheckAiModule)); result.Services.Add(executeCheck("Web.config", CheckWebConfig)); result.Services.Add(executeCheck("Web.Secret.config", CheckWebSecretConfig)); var allHealthy = result.DatabaseOk.IsOk && result.Services.All(x => x.IsOk); if (!allHealthy) { WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.InternalServerError; } return result; } private string CheckDatabase() { // Leichter DB-Ping – z.B. eine einfache Abfrage über DAOFactory DAOFactory.GenericDAO.GetAll(); return null; } private bool CheckMail() { try { // z.B. SMTP-Verbindung kurz aufbauen und sofort schließen // Kann auch weggelassen / später ergänzt werden return true; } catch { return false; } } private string CheckAiModule() { // #1 var configPath = ConfigReader.GetConfigPath(SpecialConfig.CustomPreSystemPrompt); if (!File.Exists(configPath)) return "SpecialConfig.CustomPreSystemPrompt wurde nicht korrekt konfiguriert"; var configPath2 = ConfigReader.GetConfigPath(SpecialConfig.CustomFunctionPreSystemPrompt); if (!File.Exists(configPath2)) return "SpecialConfig.CustomFunctionPreSystemPrompt wurde nicht korrekt konfiguriert"; // #2 if (string.IsNullOrEmpty(MergedConfig.GetSecretSetting(WebSecretConfigSetting.Ollama2Key))) return "Ollama2Key wurde nicht korrekt konfiguriert"; // #3 var scripts = new string[] { "Changes_2026-05-22 AiConv ActionType", "Changes_2026-06-03 AiRoutine RoutineType", "Changes_2026-06-18 AiModel default updaten", }; foreach (var script in scripts) { if (checkDatabaseScript(script) is string error) return error; } return null; } private string CheckWebConfig() { foreach (var webConfig in RequiredWebConfigs) { var url = MergedConfig.GetSetting(webConfig); if (string.IsNullOrWhiteSpace(url)) return $"'{webConfig}' wurde nicht korrekt konfiguriert"; } return null; } private string CheckWebSecretConfig() { foreach (var webSecretConfig in RequiredWebSecretConfigs) { var key = MergedConfig.GetSecretSetting(webSecretConfig); if (string.IsNullOrWhiteSpace(key)) return $"'{webSecretConfig}' wurde nicht korrekt konfiguriert"; } return null; } private string checkDatabaseScript(string name) { var executed = DAOFactory.ScriptDAO.IsScriptExecuted(name); return executed ? null : $"Script '{name}' wurde nicht ausgeführt"; } private ServiceStatusDC executeCheck(string name, Func validation) { string error; try { error = validation(); } catch (Exception ex) { error = ex.ToString(); } var ok = string.IsNullOrEmpty(error); return new ServiceStatusDC { Name = name, IsOk = ok, Message = ok ? "OK" : error }; } } }