using YTExtractor;
using Serilog;
using YTExtractor.Data;
using YTExtractor.Logging.Configuration;
using YTExtractor.Services;
using Microsoft.Extensions.DependencyInjection;

// App configuration and endpoints
var builder = WebApplication.CreateBuilder(args);

var environment = builder.Environment.EnvironmentName;

builder.Host.UseSerilog((context, services, configuration) =>
{
    builder.SetLoggerConfiguration(configuration, services, context.Configuration);
});

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<MongoDBConnector>();

// Register VTT processing service
builder.Services.AddSingleton<VttFixerService>();

// Register YoutubeExplode client
builder.Services.AddSingleton<YTExtractor.Services.YoutubeExplode.YoutubeExplodeClient>();

// Register YouTube service handlers and service
builder.Services.AddSingleton<YoutubeService>();
builder.Services.AddSingleton<YTExtractor.Services.Handlers.YoutubeExplodeHandler>();
builder.Services.AddSingleton<YTExtractor.Services.Handlers.YtDlpHandler>();

// Register Chain of Responsibility implementation
builder.Services.AddSingleton<IYoutubeService, ChainYoutubeService>();

var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();


app.MapPost("/api/video-info", async (VideoRequest request, MongoDBConnector mongo, IYoutubeService youtubeService) =>
{
    try
    {
        Log.Information("Requisição recebida");
        if (!youtubeService.IsValidYouTubeUrl(request.Url))
            return Results.BadRequest("Invalid YouTube URL");

        Log.Information("Obtendo pasta atual");
        var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
        Directory.CreateDirectory(tempDir);

        try
        {
            Log.Information($"Obtendo dados do video: {request.Url}");
            var service = new ConvertTranscriptService();
            Log.Information("Obtendo dados da url no mongo");
            var videoExists = await mongo.GetVideoByUrl(request.Url);
            if (videoExists != null)
            {
                Log.Information($"Retorno via mongo db da url: {request.Url}");
                return Results.Ok(new VideoInfo(
                    videoExists.Url,
                    videoExists.Titulo,
                    videoExists.ThumbnailUrl,
                    service.ExtractPlainText(videoExists.TranscText)
                ));
            }

            Log.Information("Obtendo dados da url na api do youtube");
            var info = await youtubeService.GetVideoInfo(request.Url, tempDir);
            var subtitles = service.ExtractPlainText(await youtubeService.GetSubtitles(request.Url, request.Language, tempDir));

            Log.Information("Guardar no mongodb");
            await mongo.InsertVideo(new VideoData
            {
                Id = Guid.NewGuid().ToString(),
                Url = request.Url,
                Titulo = info.Title,
                ThumbnailUrl = info.ThumbnailUrl,
                TranscText = subtitles
            });

            Log.Information($"Dados de video obtidos: {request.Url}");
            return Results.Ok(new VideoInfo(
                request.Url,
                info.Title,
                info.ThumbnailUrl,
                subtitles
            ));
        }
        finally
        {
            if (Directory.Exists(tempDir))
                Directory.Delete(tempDir, true);
        }
    }
    catch (Exception ex)
    {
        Log.Error(ex, "Failed to get video info");
        return Results.Problem(ex.Message);
    }
})
.WithName("GetVideoInfo")
.WithOpenApi();

app.Run();