using Microsoft.Extensions.Options; using MongoDB.Bson; using MongoDB.Driver; using Postall.Domain; using Postall.Domain.Dtos; using Postall.Domain.Entities; using Postall.Infra.MongoDB.Settings; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Channels; using System.Threading.Tasks; using static System.Runtime.InteropServices.JavaScript.JSType; namespace Postall.Infra.MongoDB.Repositories { public class ChannelRepository : IChannelRepository { private readonly IMongoCollection _channelsCollection; public ChannelRepository(IOptions mongoDbSettings) { var client = new MongoClient(mongoDbSettings.Value.ConnectionString); var database = client.GetDatabase(mongoDbSettings.Value.DatabaseName); _channelsCollection = database.GetCollection(mongoDbSettings.Value.ChannelsCollectionName); var indexKeysDefinition = Builders.IndexKeys.Ascending(c => c.YoutubeId); _channelsCollection.Indexes.CreateOne(new CreateIndexModel(indexKeysDefinition, new CreateIndexOptions { Unique = true })); var textIndexDefinition = Builders.IndexKeys .Text(c => c.Title) .Text(c => c.Description); _channelsCollection.Indexes.CreateOne(new CreateIndexModel(textIndexDefinition)); } /// /// Obtém todos os canais /// public async Task> GetAllAsync() { return await _channelsCollection.Find(c => true).ToListAsync(); } /// /// Obtém um canal pelo ID do MongoDB /// public async Task GetByIdAsync(string id) { if (!ObjectId.TryParse(id, out _)) return null; return await _channelsCollection.Find(c => c.Id == id).FirstOrDefaultAsync(); } public async Task> GetByUserIdAsync(string userId) { return await _channelsCollection.Find(c => c.UserId == userId).ToListAsync(); } /// /// Obtém os canais pelo ID do usuario e o channelId /// public async Task GetByUserIdAndChannelIdAsync(string userId, string channelId) { return await _channelsCollection.Find(c => c.UserId == userId && c.ChannelId == channelId).FirstOrDefaultAsync(); } /// /// Obtém um canal pelo ID do YouTube /// public async Task GetByYoutubeIdAsync(string youtubeId) { return await _channelsCollection.Find(c => c.YoutubeId == youtubeId).FirstOrDefaultAsync(); } /// /// Adiciona um novo canal /// public async Task AddAsync(ChannelData ChannelData) { // Verifica se o canal já existe pelo ID do YouTube var existingChannel = await GetByYoutubeIdAsync(ChannelData.YoutubeId); if (existingChannel != null) return null; // Gera novo ID para o MongoDB se não for fornecido if (string.IsNullOrEmpty(ChannelData.Id) || !ObjectId.TryParse(ChannelData.Id, out _)) { ChannelData.Id = ObjectId.GenerateNewId().ToString(); } await _channelsCollection.InsertOneAsync(ChannelData); return ChannelData; } /// /// Adiciona vários canais de uma vez /// public async Task> AddManyAsync(IEnumerable channels) { if (channels == null || !channels.Any()) return new List(); var channelsList = channels.ToList(); // Gera novos IDs para o MongoDB se necessário foreach (var ChannelData in channelsList) { if (string.IsNullOrEmpty(ChannelData.Id) || !ObjectId.TryParse(ChannelData.Id, out _)) { ChannelData.Id = ObjectId.GenerateNewId().ToString(); } } // Verifica canais existentes pelo ID do YouTube var youtubeIds = channelsList.Select(c => c.YoutubeId).ToList(); var existingChannels = await _channelsCollection .Find(c => youtubeIds.Contains(c.YoutubeId)) .ToListAsync(); var existingYoutubeIds = existingChannels.Select(c => c.YoutubeId).ToHashSet(); var newChannels = channelsList.Where(c => !existingYoutubeIds.Contains(c.YoutubeId)).ToList(); if (newChannels.Any()) await _channelsCollection.InsertManyAsync(newChannels); return newChannels; } /// /// Atualiza um canal existente /// public async Task UpdateAsync(ChannelData ChannelData) { if (string.IsNullOrEmpty(ChannelData.Id) || !ObjectId.TryParse(ChannelData.Id, out _)) return false; var result = await _channelsCollection.ReplaceOneAsync( c => c.Id == ChannelData.Id, ChannelData, new ReplaceOptions { IsUpsert = false }); return result.IsAcknowledged && result.ModifiedCount > 0; } /// /// Remove um canal pelo ID do MongoDB /// public async Task DeleteAsync(string id) { if (!ObjectId.TryParse(id, out _)) return false; var result = await _channelsCollection.DeleteOneAsync(c => c.Id == id); return result.IsAcknowledged && result.DeletedCount > 0; } /// /// Remove um canal pelo ID do YouTube /// public async Task DeleteByYoutubeIdAsync(string youtubeId) { var result = await _channelsCollection.DeleteOneAsync(c => c.YoutubeId == youtubeId); return result.IsAcknowledged && result.DeletedCount > 0; } /// /// Busca canais com base em um termo de pesquisa no título ou descrição /// public async Task> SearchAsync(string searchTerm) { if (string.IsNullOrWhiteSpace(searchTerm)) return await GetAllAsync(); var filter = Builders.Filter.Text(searchTerm); return await _channelsCollection.Find(filter).ToListAsync(); } /// /// Obtém canais selecionados (IsSelected = true) /// public async Task> GetSelectedAsync() { return await _channelsCollection.Find(c => c.IsSelected).ToListAsync(); } /// /// Marca ou desmarca um canal como selecionado /// public async Task SetSelectedStatusAsync(string id, bool isSelected) { if (!ObjectId.TryParse(id, out _)) return false; var update = Builders.Update.Set(c => c.IsSelected, isSelected); var result = await _channelsCollection.UpdateOneAsync(c => c.Id == id, update); return result.IsAcknowledged && result.ModifiedCount > 0; } /// /// Converte ChannelResponse para ChannelData /// public ChannelData ConvertFromResponse(ChannelResponse channelResponse) { if (channelResponse == null) return null; return new ChannelData { YoutubeId = channelResponse.Id, Title = channelResponse.Title, Description = channelResponse.Description, ThumbnailUrl = channelResponse.ThumbnailUrl, PublishedAt = channelResponse.PublishedAt, SubscriberCount = channelResponse.SubscriberCount, VideoCount = channelResponse.VideoCount, IsSelected = channelResponse.IsSelected }; } /// /// Converte ChannelData para ChannelResponse /// public ChannelResponse ConvertToResponse(ChannelData ChannelData) { if (ChannelData == null) return null; return new ChannelResponse { Id = ChannelData.YoutubeId, Title = ChannelData.Title, Description = ChannelData.Description, ThumbnailUrl = ChannelData.ThumbnailUrl, PublishedAt = ChannelData.PublishedAt, SubscriberCount = ChannelData.SubscriberCount, VideoCount = ChannelData.VideoCount, IsSelected = ChannelData.IsSelected }; } } }