using MahApps.Metro.Controls; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Net; using System.Net.Http; using System.Runtime.CompilerServices; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Web; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; namespace PrototypWPFHAG { /// /// Interaktionslogik für SearchWindow.xaml /// public class DocumentResponse { [JsonPropertyName("documents")] public List Documents { get; set; } } public partial class SearchWindow : MetroWindow { public readonly HttpClient _httpClient; private bool _isSearchInProgress; private readonly PdfServiceClient _pdfServiceClient = new(); private const string BaseUrl = "http://localhost:8000"; // Microservice-URL private string _selectedPdfPath; private List _selectedPdfPaths = new List(); public SearchWindow() { InitializeComponent(); _httpClient = new HttpClient { BaseAddress = new Uri(BaseUrl), Timeout = TimeSpan.FromSeconds(30) }; } private void BackToLogIn_Click(object sender, RoutedEventArgs e) { MainWindow loginWindow = new(); loginWindow.Show(); // Open new window this.Close(); // Close this window } private async void SearchButton_Click(object sender, RoutedEventArgs e) { if (_isSearchInProgress) return; try { _isSearchInProgress = true; SearchButton.IsEnabled = false; if (SearchByIdRadio.IsChecked == true) { await SearchByIdAsync(); } else { await SearchBySimilarityAsync(); } } catch (Exception ex) { MessageBox.Show($"Fehler bei der Suche: {ex.Message}", "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); } finally { _isSearchInProgress = false; SearchButton.IsEnabled = true; } } private async Task SearchByIdAsync() { if (!int.TryParse(SearchTextBox.Text, out int documentId)) { MessageBox.Show("Bitte eine gültige ID eingeben"); return; } try { var response = await _httpClient.GetAsync($"/documents/by-id/{documentId}"); var json = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(json); var documents = result.GetProperty("documents"); if (documents.GetArrayLength() == 0) { MessageBox.Show("Dokument nicht gefunden"); return; } var document = documents[0]; // Korrigierte UI-Aktualisierung await Dispatcher.InvokeAsync(() => { SearchResultsListBox.ItemsSource = new List // Änderung von SearchResult zu DocumentDetail { new DocumentDetail { Id = document.GetProperty("id").GetInt32(), DocumentName = document.GetProperty("document_name").GetString(), // Korrekter Property-Name Content = document.GetProperty("content").GetString() } }; ContentTextBox.Text = document.GetProperty("content").GetString(); // Wichtig: DisplayMemberPath korrekt setzen SearchResultsListBox.DisplayMemberPath = "DocumentName"; }); } catch (Exception ex) { MessageBox.Show($"Fehler: {ex.Message}"); } } private async Task SearchByTextAsync() { try { var encodedQuery = Uri.EscapeDataString(SearchTextBox.Text); var response = await _httpClient.GetAsync($"/documents/search?query={encodedQuery}"); var json = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(json); var documents = JsonSerializer.Deserialize>( result.GetProperty("documents").GetRawText()); MessageBox.Show($"Gefundene Dokumente: {documents?.Count}", "Debug"); SearchResultsListBox.ItemsSource = documents; SearchResultsListBox.DisplayMemberPath = "name"; } catch (Exception ex) { MessageBox.Show($"Fehler: {ex.Message}"); } } private async Task SearchBySimilarityAsync() { try { var encodedQuery = Uri.EscapeDataString(SearchTextBox.Text); var response = await _httpClient.GetAsync($"/documents/similarity?query={encodedQuery}"); var json = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); SearchResultsListBox.ItemsSource = result?.Documents; SearchResultsListBox.DisplayMemberPath = "DocumentName"; } catch (Exception ex) { MessageBox.Show($"Fehler: {ex.Message}"); } } private void PdfDropCanvas_DragEnter(object sender, DragEventArgs e) { // Nur PDF-Dateien erlauben if (e.Data.GetDataPresent(DataFormats.FileDrop)) { var files = (string[])e.Data.GetData(DataFormats.FileDrop); if (files.Any(f => System.IO.Path.GetExtension(f).Equals(".pdf", StringComparison.OrdinalIgnoreCase))) { e.Effects = DragDropEffects.Copy; DropHintText.Visibility = Visibility.Collapsed; // Platzhalter ausblenden } } else { e.Effects = DragDropEffects.None; } e.Handled = true; } private void ChoosePdfButton_Click(object sender, RoutedEventArgs e) { var openFileDialog = new Microsoft.Win32.OpenFileDialog { Filter = "PDF Files (*.pdf)|*.pdf", Multiselect = true }; if (openFileDialog.ShowDialog() == true) { _selectedPdfPaths.AddRange(openFileDialog.FileNames); PdfIcon.Visibility = Visibility.Visible; PdfFileNameText.Text = string.Join(", ", _selectedPdfPaths.Select(System.IO.Path.GetFileName)); PdfFileNameText.Visibility = Visibility.Visible; DropHintText.Visibility = Visibility.Collapsed; } } private void PdfDropCanvas_Drop(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); var pdfFiles = files.Where(f => System.IO.Path.GetExtension(f).Equals(".pdf", StringComparison.OrdinalIgnoreCase)).ToList(); if (pdfFiles.Any()) { _selectedPdfPaths.AddRange(pdfFiles); // 更新UI以显示所有文件 PdfIcon.Visibility = Visibility.Visible; PdfFileNameText.Text = string.Join(", ", _selectedPdfPaths.Select(System.IO.Path.GetFileName)); PdfFileNameText.Visibility = Visibility.Visible; DropHintText.Visibility = Visibility.Collapsed; } } } // Response-Klassen public class ApiResponse { [JsonPropertyName("success")] public bool Success { get; set; } [JsonPropertyName("document")] public DocumentDetail Document { get; set; } [JsonPropertyName("documents")] public List Documents { get; set; } } public class DocumentDetail { [JsonPropertyName("id")] public int Id { get; set; } [JsonPropertyName("document_name")] public string DocumentName { get; set; } [JsonPropertyName("content")] public string Content { get; set; } [JsonPropertyName("distance")] public double Distance { get; set; } // Für die TextBox-Bindung private bool _isSelected; public bool IsSelected { get => _isSelected; set { _isSelected = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class ApiError { public string Detail { get; set; } } private async void UploadButton_Click(object sender, RoutedEventArgs e) { if (!_selectedPdfPaths.Any()) { MessageBox.Show("Keine PDF ausgewählt!"); return; } // luis // UI zurücksetzen UploadProgressBar.Visibility = Visibility.Visible; UploadProgressBar.Value = 0; UploadStatusText.Text = "Upload läuft..."; try { int totalFiles = _selectedPdfPaths.Count; int currentFile = 0; foreach (var pdfPath in _selectedPdfPaths) { currentFile++; UploadStatusText.Text = $"Upload {currentFile}/{totalFiles}: {System.IO.Path.GetFileName(pdfPath)}"; using (var httpClient = new HttpClient()) using (var fileStream = File.OpenRead(pdfPath)) { var content = new StreamContent(fileStream); var formData = new MultipartFormDataContent(); formData.Add(content, "file", System.IO.Path.GetFileName(pdfPath)); var response = await httpClient.PostAsync($"{BaseUrl}/upload-pdf", formData); if (response.IsSuccessStatusCode) { UploadStatusText.Text = $"Erfolgreich hochgeladen: {System.IO.Path.GetFileName(pdfPath)}"; } else { UploadStatusText.Text = $"Fehler beim Upload von {System.IO.Path.GetFileName(pdfPath)}"; } } } // Canvas zurücksetzen Dispatcher.Invoke(() => { PdfIcon.Visibility = Visibility.Collapsed; PdfFileNameText.Visibility = Visibility.Collapsed; DropHintText.Visibility = Visibility.Visible; _selectedPdfPaths.Clear(); }); // Erfolgsmeldung nach 3 Sekunden ausblenden await Task.Delay(3000); UploadStatusText.Text = string.Empty; } catch (Exception ex) { UploadStatusText.Text = $"Fehler: {ex.Message}"; } finally { UploadProgressBar.Visibility = Visibility.Collapsed; } } private async void DeleteButton_Click(object sender, RoutedEventArgs e) { if (SearchResultsListBox.SelectedItems.Count == 0) { MessageBox.Show("Bitte Dokumente auswählen."); return; } var result = MessageBox.Show( $"{SearchResultsListBox.SelectedItems.Count} Dokument(e) löschen?", "Bestätigung", MessageBoxButton.YesNo, MessageBoxImage.Warning ); if (result != MessageBoxResult.Yes) return; var deletedIds = new List(); var errorIds = new List(); foreach (var item in SearchResultsListBox.SelectedItems.Cast().ToList()) { try { var response = await _httpClient.DeleteAsync($"/documents/by-id/{item.Id}/delete"); if (response.IsSuccessStatusCode) { deletedIds.Add(item.Id); Debug.WriteLine($"Gelöscht: {item.Id}"); } else { errorIds.Add(item.Id); var errorContent = await response.Content.ReadAsStringAsync(); Debug.WriteLine($"Fehler bei {item.Id}: {errorContent}"); } } catch (Exception ex) { errorIds.Add(item.Id); Debug.WriteLine($"Ausnahme: {ex.Message}"); } } // Aktualisiere die Liste unabhängig vom Suchmodus if (SearchByIdRadio.IsChecked == true) { await SearchByIdAsync(); // Neu laden der ID-Suche } else { await SearchBySimilarityAsync(); // Neu laden der Textsuche } // Feedback an Benutzer var message = new StringBuilder(); if (deletedIds.Count > 0) { message.AppendLine($"{deletedIds.Count} Dokument(e) gelöscht."); } if (errorIds.Count > 0) { message.AppendLine($"{errorIds.Count} Dokument(e) konnten nicht gelöscht werden."); } MessageBox.Show(message.ToString()); } private async void SearchResultsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (SearchResultsListBox.SelectedItem is DocumentDetail selected) { try { var response = await _httpClient.GetAsync($"/documents/{selected.Id}/markdown"); var content = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(content); ContentTextBox.Text = result.GetProperty("document") .GetProperty("content") .GetString(); } catch (Exception ex) { ContentTextBox.Text = $"Fehler: {ex.Message}"; } } } } }