using BLAIzor.Data;
using BLAIzor.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.Identity.Client;
using BLAIzor.Helpers;
using Qdrant.Client.Grpc;
using System.Collections;
namespace BLAIzor.Services
{
public class ContentEditorService
{
#region Private Fields
private readonly OpenAIApiService _openAIApiService;
private readonly QDrantService _qDrantService;
private readonly HtmlSnippetProcessor _htmlSnippetProcessor;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ScopedContentService _scopedContentService;
private readonly OpenAIEmbeddingService _openAIEmbeddingService;
private readonly LocalEmbeddingService _localEmbeddingService;
private readonly ISimpleLogger _logger;
public static IConfiguration? _configuration;
#endregion
#region Constructor
///
/// Initializes a new instance of the class.
///
/// The OpenAI API service.
/// The Qdrant service.
/// The OpenAI embedding service.
/// The local embedding service.
/// The HTML snippet processor.
/// The service scope factory for creating database contexts.
/// The scoped content service.
/// The application configuration.
public ContentEditorService(OpenAIApiService openAIApiService,
QDrantService qDrantService,
OpenAIEmbeddingService openAIEmbeddingService,
LocalEmbeddingService localEmbeddingService,
HtmlSnippetProcessor htmlSnippetProcessor,
IServiceScopeFactory serviceScopeFactory,
ScopedContentService scopedContentService,
IConfiguration? configuration,
ISimpleLogger logger)
{
_openAIApiService = openAIApiService;
_qDrantService = qDrantService;
_openAIEmbeddingService = openAIEmbeddingService;
_localEmbeddingService = localEmbeddingService;
_htmlSnippetProcessor = htmlSnippetProcessor;
_serviceScopeFactory = serviceScopeFactory;
_scopedContentService = scopedContentService;
_configuration = configuration;
_logger = logger;
}
#endregion
#region Private Helper Methods
///
/// Retrieves the AI embedding service setting from the configuration.
///
/// The name of the embedding service (e.g., "local", "openai").
private string GetAiEmbeddingSettings() =>
_configuration?.GetSection("AiSettings")?.GetValue("EmbeddingService") ?? string.Empty;
///
/// Removes content chunks and their corresponding Qdrant entries by their IDs.
///
/// A list of content chunk IDs to remove.
/// The name of the Qdrant collection.
/// A representing the asynchronous operation.
private async Task RemoveChunksAndQdrantEntriesByIdsAsync(List chunkIds, string collectionName)
{
using var scope = _serviceScopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService();
var chunks = await db.ContentChunks
.Where(c => chunkIds.Contains(c.Id))
.ToListAsync();
var pointIds = chunks.Select(c => Guid.Parse(c.QdrantPointId)).ToArray();
await _qDrantService.DeletePointsAsync(pointIds, collectionName);
db.ContentChunks.RemoveRange(chunks);
await db.SaveChangesAsync();
}
///
/// Generates a unique vector collection name for a given site.
///
/// The site information.
/// A generated vector collection name.
public string GetGeneratedVectorCollectionName(SiteInfo siteInfo)
{
var safeName = siteInfo.SiteName?.ToLower().Replace(" ", "_").Replace("-", "_");
return $"site_{safeName}_{Guid.NewGuid().ToString().Substring(0, 8)}";
}
#endregion
#region MenuItem CRUD Operations
///
/// Adds a new menu item to the database.
///
/// The menu item to add.
/// The added menu item with its generated ID.
public async Task