using BaseDomain.Results;
using Microsoft.AspNetCore.Http;
using Postall.Domain;
using Postall.Domain.Contracts.Repositories;
using Postall.Domain.Dtos;
using Postall.Domain.Entities;
using Postall.Domain.Services.Contracts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Postall.Infra.Services
{
public class VideoService : IVideoService
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IVideoRepository _videoRepository;
private readonly IChannelRepository _channelRepository;
private readonly IVideoYoutubeService _videoYoutubeService;
public VideoService(
IHttpContextAccessor httpContextAccessor,
IVideoRepository videoRepository,
IChannelRepository channelRepository,
IVideoYoutubeService videoYoutubeService)
{
_httpContextAccessor = httpContextAccessor;
_videoRepository = videoRepository;
_channelRepository = channelRepository;
_videoYoutubeService = videoYoutubeService;
}
///
/// Obtém o ID do usuário atual a partir das claims
///
private string GetCurrentUserId()
{
var user = _httpContextAccessor.HttpContext.User;
var userId = user.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
var email = user.FindFirst(ClaimTypes.Email)?.Value;
if (!string.IsNullOrEmpty(email))
{
userId = Convert.ToBase64String(
System.Text.Encoding.UTF8.GetBytes(email)
).Replace("/", "_").Replace("+", "-").Replace("=", "");
}
}
return userId;
}
///
/// Obtém todos os vídeos do usuário atual
///
public async Task>> GetUserVideosAsync()
{
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return new List();
var videos = await _videoRepository.GetByUserIdAsync(userId);
return videos.Select(v => v.ToVideoResponse()).ToList();
}
///
/// Obtém os vídeos de um canal específico para o usuário atual
///
public async Task>> GetVideosByChannelIdAsync(string channelId)
{
if (string.IsNullOrEmpty(channelId))
return new List();
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return new List();
var videos = await _videoRepository.GetByUserIdAndChannelIdAsync(userId, channelId);
return videos.Select(v => v.ToVideoResponse()).ToList();
}
///
/// Obtém os detalhes de um vídeo específico
///
public async Task> GetVideoDetailsAsync(string videoId)
{
if (string.IsNullOrEmpty(videoId))
return Result.Failure("ID do vídeo inválido");
var videoDetails = await _videoYoutubeService.GetVideoDetailsAsync(videoId);
return videoDetails;
}
///
/// Obtém os vídeos de um canal diretamente do YouTube
///
public async Task>> GetChannelVideosFromYouTubeAsync(string channelId, int maxResults = 10)
{
if (string.IsNullOrEmpty(channelId))
return Result>.Failure("ID do canal inválido");
// Verifica se o canal existe para o usuário
var userId = GetCurrentUserId();
var channel = await _channelRepository.GetByUserIdAndChannelIdAsync(userId, channelId);
if (channel == null)
return Result>.Failure("Canal não encontrado para este usuário");
// Obtém os vídeos que o usuário já adicionou para este canal
var userVideos = await _videoRepository.GetByUserIdAndChannelIdAsync(userId, channelId);
var userVideoIds = userVideos.Select(v => v.VideoId).ToHashSet();
// Busca os vídeos do canal no YouTube
var channelVideos = await _videoYoutubeService.GetChannelVideosAsync(channelId, maxResults);
if (!channelVideos.IsSuccess)
return channelVideos;
// Marca os vídeos que já foram adicionados pelo usuário
foreach (var video in channelVideos.Value)
{
if (userVideoIds.Contains(video.VideoId))
{
// Esse vídeo já foi adicionado pelo usuário
video.Id = userVideos.First(v => v.VideoId == video.VideoId).Id;
}
}
return channelVideos;
}
///
/// Adiciona um vídeo à lista do usuário
///
public async Task> AddVideoAsync(string videoId, string channelId)
{
if (string.IsNullOrEmpty(videoId))
return Result.Failure("ID do vídeo inválido");
if (string.IsNullOrEmpty(channelId))
return Result.Failure("ID do canal inválido");
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return Result.Failure("Usuário não identificado");
// Verifica se o canal existe para o usuário
var channel = await _channelRepository.GetByUserIdAndChannelIdAsync(userId, channelId);
if (channel == null)
return Result.Failure("Canal não encontrado para este usuário");
// Verifica se o vídeo já existe para o usuário
var existingVideo = await _videoRepository.GetByUserIdAndVideoIdAsync(userId, videoId);
if (existingVideo != null)
return true; // Vídeo já existe, retorna sucesso
try
{
// Obtém os detalhes do vídeo do YouTube
var videoDetails = await _videoYoutubeService.GetVideoDetailsAsync(videoId);
if (!videoDetails.IsSuccess)
return Result.Failure(videoDetails.Error);
// Cria o objeto de dados do vídeo
var videoData = new VideoData
{
UserId = userId,
ChannelId = channelId,
VideoId = videoId,
Title = videoDetails.Value.Title,
Description = videoDetails.Value.Description,
ThumbnailUrl = videoDetails.Value.ThumbnailUrl,
PublishedAt = videoDetails.Value.PublishedAt,
ViewCount = videoDetails.Value.ViewCount,
LikeCount = videoDetails.Value.LikeCount,
DislikeCount = videoDetails.Value.DislikeCount,
CommentCount = videoDetails.Value.CommentCount,
CreatedAt = DateTime.UtcNow
};
// Adiciona o vídeo ao repositório
await _videoRepository.AddAsync(videoData);
return true;
}
catch (Exception ex)
{
return Result.Failure(ex.Message);
}
}
///
/// Adiciona múltiplos vídeos à lista do usuário
///
public async Task> AddVideosAsync(List videoIds, string channelId)
{
if (videoIds == null || !videoIds.Any())
return Result.Failure("Lista de IDs de vídeos inválida");
if (string.IsNullOrEmpty(channelId))
return Result.Failure("ID do canal inválido");
var userId = GetCurrentUserId();
if (string.IsNullOrEmpty(userId))
return Result.Failure("Usuário não identificado");
// Verifica se o canal existe para o usuário
var channel = await _channelRepository.GetByUserIdAndChannelIdAsync(userId, channelId);
if (channel == null)
return Result.Failure("Canal não encontrado para este usuário");
// Obtém os vídeos que o usuário já adicionou
var existingVideos = await _videoRepository.GetByUserIdAsync(userId);
var existingVideoIds = existingVideos.Select(v => v.VideoId).ToHashSet();
// Filtra os vídeos que ainda não foram adicionados
var newVideoIds = videoIds.Where(id => !existingVideoIds.Contains(id)).ToList();
if (newVideoIds.Count == 0)
return true; // Todos os vídeos já existem
try
{
var videoDataList = new List();
// Obtém os detalhes de cada vídeo do YouTube e cria os objetos de dados
foreach (var videoId in newVideoIds)
{
var videoDetails = await _videoYoutubeService.GetVideoDetailsAsync(videoId);
if (videoDetails.IsSuccess)
{
videoDataList.Add(new VideoData
{
UserId = userId,
ChannelId = channelId,
VideoId = videoId,
Title = videoDetails.Value.Title,
Description = videoDetails.Value.Description,
ThumbnailUrl = videoDetails.Value.ThumbnailUrl,
PublishedAt = videoDetails.Value.PublishedAt,
ViewCount = videoDetails.Value.ViewCount,
LikeCount = videoDetails.Value.LikeCount,
DislikeCount = videoDetails.Value.DislikeCount,
CommentCount = videoDetails.Value.CommentCount,
CreatedAt = DateTime.UtcNow
});
}
}
// Adiciona os vídeos ao repositório
if (videoDataList.Any())
{
await _videoRepository.AddManyAsync(videoDataList);
}
return true;
}
catch (Exception ex)
{
return Result.Failure(ex.Message);
}
}
///
/// Remove um vídeo da lista do usuário
///
public async Task> RemoveVideoAsync(string videoId)
{
if (string.IsNullOrEmpty(videoId))
return Result.Failure("ID do vídeo inválido");
try
{
await _videoRepository.DeleteAsync(videoId);
return true;
}
catch (Exception ex)
{
return Result.Failure(ex.Message);
}
}
///
/// Busca vídeos no YouTube pelo título ou descrição
///
public async Task>> SearchVideosAsync(string query, int maxResults = 10)
{
if (string.IsNullOrEmpty(query) || query.Length < 3)
return new List();
var results = await _videoYoutubeService.SearchVideosAsync(query, maxResults);
return results;
}
}
}