using Microsoft.Extensions.Logging;
using SumaTube.Application.Videos.Contracts;
using SumaTube.Domain.Entities.Videos;
using SumaTube.Infra.Contracts.Repositories.Videos;
using SumaTube.Infra.VideoSumarizer.Contracts;
using SumaTube.Infra.VideoSumarizer.Videos;

namespace SumaTube.Application.Videos.ApplicationServices
{
    public class VideoApplicationService : IVideoApplicationService
    {
        private readonly IVideoSummaryRepository _repository;
        private readonly IVideoSumarizerService _sumarizerService;
        private readonly ILogger<VideoApplicationService> _logger;

        public VideoApplicationService(
            IVideoSummaryRepository repository,
            IVideoSumarizerService sumarizerService,
            ILogger<VideoApplicationService> logger)
        {
            _repository = repository;
            _sumarizerService = sumarizerService;
            _logger = logger;
        }

        public async Task<List<VideoSummary>> GetUserVideosAsync(string userId)
        {
            _logger.LogInformation("Obtendo videos do usuário: {UserId}", userId);
            return await _repository.GetByUserIdAsync(userId);
        }

        public async Task<VideoSummary> GetVideoSummaryByIdAsync(string id, string userId)
        {
            _logger.LogInformation("Obtendo resumo com ID: {SummaryId} para usuário: {UserId}", id, userId);
            var summary = await _repository.GetByIdAsync(id);

            if (summary == null || summary.UserId != userId)
            {
                _logger.LogWarning("Resumo não encontrado ou acesso não autorizado. ID: {SummaryId}, UserId: {UserId}", id, userId);
                return null;
            }

            return summary;
        }

        public async Task<VideoSummary> RequestVideoSummaryAsync(string youtubeUrl, string language, string userId)
        {
            _logger.LogInformation("Solicitando resumo para URL: {Url}, idioma: {Language}, usuário: {UserId}", youtubeUrl, language, userId);

            try
            {
                // Extrair ID do vídeo
                string videoId = ExtractVideoId(youtubeUrl);

                if (string.IsNullOrEmpty(videoId))
                {
                    _logger.LogWarning("URL do YouTube inválida: {Url}", youtubeUrl);
                    throw new ArgumentException("URL do YouTube inválida");
                }

                // Verificar se já existe um resumo para este vídeo/usuário/idioma
                bool exists = await _repository.ExistsAsync(videoId, userId, language);

                if (exists)
                {
                    _logger.LogInformation("Resumo já existente para vídeo: {VideoId}, usuário: {UserId}, idioma: {Language}",
                        videoId, userId, language);
                    return await _repository.GetByVideoIdAndUserIdAndLanguageAsync(videoId, userId, language);
                }

                // Criar novo resumo
                var sessionId = Guid.NewGuid().ToString();
                var summary = VideoSummary.Create(videoId, userId, language, sessionId);

                // Salvar no repositório
                await _repository.AddAsync(summary);

                // Enviar para processamento via RabbitMQ
                _logger.LogInformation("Enviando solicitação para processamento. SessionId: {SessionId}", sessionId);
                await _sumarizerService.RequestVideoSummarization(sessionId, youtubeUrl, language);

                return summary;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao solicitar resumo de vídeo: {Message}", ex.Message);
                throw;
            }
        }

        public async Task<object> CheckSummaryStatusAsync(string id, string userId)
        {
            _logger.LogInformation("Verificando status do resumo. ID: {SummaryId}, usuário: {UserId}", id, userId);

            var summary = await _repository.GetByIdAsync(id);

            if (summary == null || summary.UserId != userId)
            {
                _logger.LogWarning("Resumo não encontrado ou acesso não autorizado. ID: {SummaryId}, UserId: {UserId}", id, userId);
                return new { status = "NOT_FOUND" };
            }

            return new
            {
                status = summary.Status,
                title = summary.Title,
                thumbnailUrl = summary.ThumbnailUrl,
                errorMessage = summary.ErrorMessage
            };
        }

        private string ExtractVideoId(string url)
        {
            try
            {
                var uri = new Uri(url);

                if (uri.Host.Contains("youtube.com"))
                {
                    var query = System.Web.HttpUtility.ParseQueryString(uri.Query);
                    return query["v"];
                }
                else if (uri.Host.Contains("youtu.be"))
                {
                    var segments = uri.Segments;
                    return segments[segments.Length - 1].TrimEnd('/');
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao extrair ID do vídeo da URL: {Url}", url);
            }

            return null;
        }
    }
}
