using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Polly;
using Polly.Extensions.Http;
using Serilog;
using SaasMediaWorker.Configuration;
using SaasMediaWorker.Services;

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.Console(outputTemplate:
        "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
    .CreateLogger();

try
{
    Log.Information("🚀 ContentGen AI Media Worker başlatılıyor...");

    var builder = Host.CreateApplicationBuilder(args);

    builder.Services.AddSerilog();

    // Configuration binding
    builder.Services.Configure<WorkerSettings>(
        builder.Configuration.GetSection("WorkerSettings"));
    builder.Services.Configure<RedisSettings>(
        builder.Configuration.GetSection("Redis"));
    builder.Services.Configure<S3Settings>(
        builder.Configuration.GetSection("S3"));
    builder.Services.Configure<ApiSettings>(
        builder.Configuration.GetSection("ApiSettings"));
    builder.Services.Configure<FFmpegSettings>(
        builder.Configuration.GetSection("FFmpeg"));

    // Polly Retry Policy — Exponential Backoff + Circuit Breaker
    var retryPolicy = HttpPolicyExtensions
        .HandleTransientHttpError()
        .WaitAndRetryAsync(
            retryCount: 3,
            sleepDurationProvider: attempt =>
                TimeSpan.FromSeconds(Math.Pow(2, attempt)) +
                TimeSpan.FromMilliseconds(Random.Shared.Next(0, 1000)),
            onRetry: (outcome, delay, attempt, _) =>
            {
                Log.Warning(
                    "HTTP Retry #{Attempt} — {Delay}s sonra tekrar denenecek. Hata: {Error}",
                    attempt, delay.TotalSeconds,
                    outcome.Exception?.Message ?? outcome.Result?.StatusCode.ToString());
            });

    var circuitBreakerPolicy = HttpPolicyExtensions
        .HandleTransientHttpError()
        .CircuitBreakerAsync(
            handledEventsAllowedBeforeBreaking: 5,
            durationOfBreak: TimeSpan.FromSeconds(30),
            onBreak: (_, duration) =>
                Log.Error("⚡ Circuit Breaker AÇILDI — {Duration}s bekleniyor", duration.TotalSeconds),
            onReset: () =>
                Log.Information("✅ Circuit Breaker kapandı — istekler devam ediyor"));

    var combinedPolicy = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy);

    // HttpClient registrations with Polly
    builder.Services.AddHttpClient<HiggsFieldService>("HiggsField")
        .AddPolicyHandler(combinedPolicy);

    builder.Services.AddHttpClient<TtsService>("TTS")
        .AddPolicyHandler(combinedPolicy);

    builder.Services.AddHttpClient<OpenAiTtsService>("OpenAITTS")
        .AddPolicyHandler(combinedPolicy);

    builder.Services.AddHttpClient<SunoMusicService>("Suno")
        .AddPolicyHandler(combinedPolicy);

    builder.Services.AddHttpClient<AudioCraftService>("AudioCraft")
        .AddPolicyHandler(combinedPolicy);

    builder.Services.AddHttpClient<ApiNotificationService>("CoreAPI")
        .AddPolicyHandler(retryPolicy);

    // Service registrations
    builder.Services.AddSingleton<S3StorageService>();
    builder.Services.AddSingleton<FFmpegService>();
    builder.Services.AddSingleton<RemotionService>();
    builder.Services.AddSingleton<VideoRenderPipeline>();
    builder.Services.AddSingleton<DatabaseService>();

    // Background Service — Redis Queue Consumer
    builder.Services.AddHostedService<QueueConsumerService>();

    var host = builder.Build();
    await host.RunAsync();
}
catch (Exception ex)
{
    Log.Fatal(ex, "💀 Media Worker başlatılamadı!");
}
finally
{
    await Log.CloseAndFlushAsync();
}
