using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; using Microsoft.EntityFrameworkCore; namespace AuthorBuddy.Web.Services; public class SettingsService : ISettingsService { private const string KeyOllamaUrl = "ollama_url"; private const string KeyRagModel = "ollama_rag_model"; private const string KeyStyleModel = "ollama_style_model"; private const string KeySpellingModel = "ollama_spelling_model"; private const string KeyTheme = "theme"; private const string KeyLektorPrompt = "ollama_lektor_prompt"; private const string KeyFactCheckTemplate = "ollama_fact_check"; private const string KeySpellingPrompt = "ollama_spelling_prompt"; private readonly IDbContextFactory _contextFactory; private readonly OllamaSettings _ollamaConfig; private int? _currentUserId; private int? _currentProjectId; public SettingsService(IDbContextFactory contextFactory, OllamaSettings ollamaConfig) { _contextFactory = contextFactory; _ollamaConfig = ollamaConfig; } public int? CurrentProjectId { get => _currentProjectId; set => _currentProjectId = value; } private async Task GetSettingAsync(string key, int? userId, int? projectId) { await using var context = await _contextFactory.CreateDbContextAsync(); var matches = context.Settings.Where(s => s.Key == key && (s.UserId == userId || s.UserId == null) && (s.ProjectId == projectId || s.ProjectId == null)); var setting = await matches .OrderByDescending(s => s.UserId != null) .ThenByDescending(s => s.ProjectId != null) .FirstOrDefaultAsync(); return setting?.Value; } private async Task GetAsync(string key) { return await GetSettingAsync(key, _currentUserId, _currentProjectId); } private async Task SetAsync(string key, string value) { await using var context = await _contextFactory.CreateDbContextAsync(); var existing = await context.Settings .Where(s => s.Key == key && s.UserId == _currentUserId && s.ProjectId == _currentProjectId) .FirstOrDefaultAsync(); if (existing != null) { existing.Value = value; } else { context.Settings.Add(new SettingEntity { Key = key, Value = value, UserId = _currentUserId, ProjectId = _currentProjectId }); } await context.SaveChangesAsync(); } public Task GetOllamaUrlAsync() => GetAsync(KeyOllamaUrl); public Task GetRagModelAsync() => GetAsync(KeyRagModel); public Task GetStyleModelAsync() => GetAsync(KeyStyleModel); public Task GetLektorSystemPromptAsync() => GetAsync(KeyLektorPrompt); public Task GetFactCheckTemplateAsync() => GetAsync(KeyFactCheckTemplate); public Task GetSpellingPromptAsync() => GetAsync(KeySpellingPrompt); public Task GetSpellingModelAsync() => GetAsync(KeySpellingModel); public Task GetThemeAsync() => GetAsync(KeyTheme); public async Task SaveOllamaUrlAsync(string url) { await SetAsync(KeyOllamaUrl, url); _ollamaConfig.OllamaUrl = url; } public async Task SaveRagModelAsync(string model) { await SetAsync(KeyRagModel, model); _ollamaConfig.StyleModel = model; } public async Task SaveStyleModelAsync(string model) { await SetAsync(KeyStyleModel, model); _ollamaConfig.StyleModel = model; } public async Task SaveLektorSystemPromptAsync(string prompt) { await SetAsync(KeyLektorPrompt, prompt); _ollamaConfig.LektorSystemPrompt = prompt; } public async Task SaveFactCheckTemplateAsync(string prompt) { await SetAsync(KeyFactCheckTemplate, prompt); _ollamaConfig.FactCheckTemplate = prompt; } public async Task SaveSpellingPromptAsync(string prompt) { await SetAsync(KeySpellingPrompt, prompt); _ollamaConfig.SpellingPrompt = prompt; } public async Task SaveSpellingModelAsync(string model) { await SetAsync(KeySpellingModel, model); _ollamaConfig.SpellingModel = model; } public Task SaveThemeAsync(string theme) => SetAsync(KeyTheme, theme); public async Task> GetUsersAsync() { await using var context = await _contextFactory.CreateDbContextAsync(); return await context.Users.ToListAsync(); } public async Task GetCurrentUserAsync() { await using var context = await _contextFactory.CreateDbContextAsync(); var user = await context.Users.FirstOrDefaultAsync(u => u.IsCurrent); return user ?? await context.Users.FirstAsync(); } public async Task SetCurrentUserAsync(int userId) { await using var context = await _contextFactory.CreateDbContextAsync(); var users = await context.Users.ToListAsync(); foreach (var u in users) u.IsCurrent = u.Id == userId; await context.SaveChangesAsync(); _currentUserId = userId; } public async Task CreateUserAsync(string name) { await using var context = await _contextFactory.CreateDbContextAsync(); var user = new UserEntity { Name = name }; context.Users.Add(user); await context.SaveChangesAsync(); return user; } public async Task InitializeAsync() { await using var context = await _contextFactory.CreateDbContextAsync(); var userExists = await context.Users.AnyAsync(); if (!userExists) { var defaultUser = new UserEntity { Name = "Standardbenutzer", IsCurrent = true }; context.Users.Add(defaultUser); await context.SaveChangesAsync(); _currentUserId = defaultUser.Id; } else { var current = await context.Users.FirstOrDefaultAsync(u => u.IsCurrent); _currentUserId = current?.Id ?? (await context.Users.FirstAsync()).Id; } var entries = new (string Key, string Default)[] { (KeyOllamaUrl, _ollamaConfig.OllamaUrl), (KeyRagModel, _ollamaConfig.StyleModel), (KeyStyleModel, _ollamaConfig.StyleModel), (KeySpellingModel, _ollamaConfig.SpellingModel), (KeyTheme, _ollamaConfig.Theme), (KeyLektorPrompt, _ollamaConfig.LektorSystemPrompt), (KeyFactCheckTemplate, _ollamaConfig.FactCheckTemplate), (KeySpellingPrompt, _ollamaConfig.SpellingPrompt), }; foreach (var entry in entries) { var existing = await context.Settings .Where(s => s.Key == entry.Key && s.UserId == _currentUserId && s.ProjectId == null) .FirstOrDefaultAsync(); if (existing != null) { var val = existing.Value; if (entry.Key == KeyOllamaUrl) _ollamaConfig.OllamaUrl = val; else if (entry.Key == KeyRagModel) _ollamaConfig.StyleModel = val; else if (entry.Key == KeyStyleModel) _ollamaConfig.StyleModel = val; else if (entry.Key == KeySpellingModel) _ollamaConfig.SpellingModel = val; else if (entry.Key == KeyTheme) _ollamaConfig.Theme = val; else if (entry.Key == KeyLektorPrompt) _ollamaConfig.LektorSystemPrompt = val; else if (entry.Key == KeyFactCheckTemplate) _ollamaConfig.FactCheckTemplate = val; else if (entry.Key == KeySpellingPrompt) _ollamaConfig.SpellingPrompt = val; } else { context.Settings.Add(new SettingEntity { Key = entry.Key, Value = entry.Default, UserId = _currentUserId, ProjectId = null }); } } await context.SaveChangesAsync(); } }