using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using MongoDB.Driver;
using OnlyOneAccessTemplate.Models;
using OnlyOneAccessTemplate.Services;

var builder = WebApplication.CreateBuilder(args);

// Configurações otimizadas para produção ARM64
if (builder.Environment.IsProduction())
{
    // Configurar Kestrel para melhor performance
    builder.WebHost.ConfigureKestrel(options =>
    {
        options.Limits.MaxConcurrentConnections = 100;
        options.Limits.MaxConcurrentUpgradedConnections = 100;
        options.Limits.MaxRequestBodySize = 10 * 1024 * 1024; // 10MB
        options.Limits.MinRequestBodyDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
        options.Limits.MinResponseDataRate = new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
        options.AddServerHeader = false;
    });

    // Configurações de logging otimizadas
    builder.Logging.ClearProviders();
    builder.Logging.AddConsole();
    builder.Logging.SetMinimumLevel(LogLevel.Warning);
}

// Add services to the container.
builder.Services.AddControllersWithViews(options =>
{
    if (builder.Environment.IsProduction())
    {
        // Configurações de cache para produção
        options.CacheProfiles.Add("Default", new CacheProfile()
        {
            Duration = 300 // 5 minutos
        });
    }
});

// Configurar Response Caching
builder.Services.AddResponseCaching(options =>
{
    options.MaximumBodySize = 1024 * 1024; // 1MB
    options.UseCaseSensitivePaths = false;
});

// Configurar Response Compression
builder.Services.AddResponseCompression(options =>
{
    options.EnableForHttps = true;
});

// Add services to the container
builder.Services.AddControllersWithViews();

// Session support
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(30);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

// MongoDB Configuration
builder.Services.AddSingleton<IMongoClient>(sp =>
{
    var connectionString = builder.Configuration.GetConnectionString("MongoDB");
    return new MongoClient(connectionString);
});


// Rate Limiting Service
builder.Services.AddScoped<IRateLimitService, RateLimitService>();

// Configuration Service (para substituir o ISiteConfigurationService se necessário)
builder.Services.AddScoped<IConfigurationService, ConfigurationService>();

// Configuração de localização para SEO multi-idioma
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[] { "pt-BR", "en-US", "es-ES" };
    options.SetDefaultCulture(supportedCultures[0])
           .AddSupportedCultures(supportedCultures)
           .AddSupportedUICultures(supportedCultures);
}); 

builder.Services.AddScoped(sp =>
{
    var client = sp.GetRequiredService<IMongoClient>();
    var databaseName = builder.Configuration.GetValue<string>("MongoDB:DatabaseName");
    return client.GetDatabase(databaseName);
});

// Custom Services
builder.Services.AddScoped<ISiteConfigurationService, SiteConfigurationService>();
builder.Services.AddScoped<ILanguageService, LanguageService>();
builder.Services.AddScoped<ISeoService, SeoService>();
builder.Services.AddScoped<IConversionService, ConversionService>();

builder.Services.AddScoped<IModuleService, ModuleService>();
builder.Services.AddHttpClient<IModuleService, ModuleService>();

// Converter Services - Registrar todos os conversores dispon�veis
builder.Services.AddScoped<TextCaseConverterService>();
builder.Services.AddScoped<CsvToJsonConverterService>();
builder.Services.AddScoped<ImageToTextConverterService>();

// Substituindo UpperLowerConversorService por API com Polly
builder.Services.AddHttpClient<ITextConversionApiService, TextConversionApiService>();
builder.Services.AddScoped<ApiBasedSentenceConverterService>();

// HttpClient for external calls
builder.Services.AddHttpClient<ConversionService>();
builder.Services.AddHttpClient<ImageToTextConverterService>();

// Response Compression
builder.Services.AddResponseCompression(options =>
{
    options.EnableForHttps = true;
});

// Response Caching
builder.Services.AddResponseCaching();

// Memory Cache
builder.Services.AddMemoryCache();

// Loggingbuilder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddDebug();

var app = builder.Build();

// Configure the HTTP request pipeline
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = ctx =>
    {
        // Cache estático por 1 hora
        ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=3600");
    }
});

// Session
app.UseSession();

// Response Compression & Caching
app.UseResponseCompression();
app.UseResponseCaching();

app.UseRequestLocalization();

// Middleware para detectar configuração por domínio
app.Use(async (context, next) =>
{
    var host = context.Request.Host.Host;
    var configService = context.RequestServices.GetRequiredService<IConfigurationService>();
    var config = await configService.GetConfigurationAsync(host);
    context.Items["SiteConfig"] = config;

    // Se não encontrou config por domínio, usar fallback baseado no idioma da URL
    if (config == null)
    {
        var pathSegments = context.Request.Path.Value?.Split('/', StringSplitOptions.RemoveEmptyEntries);
        var language = "pt"; // default

        if (pathSegments?.Length > 0 && new[] { "en", "es", "pt" }.Contains(pathSegments[0]))
        {
            language = pathSegments[0];
        }

        // Usar seu serviço existente como fallback
        var siteConfigService = context.RequestServices.GetRequiredService<ISiteConfigurationService>();
        var fallbackConfig = await siteConfigService.GetConfigurationAsync(language);
        context.Items["SiteConfig"] = fallbackConfig;
    }

    await next();
});


app.UseRouting();

// Custom routing for multilingual support
app.MapControllerRoute(
    name: "converter-api",
    pattern: "converter/api/{action}/{converterType?}",
    defaults: new { controller = "Converter" });

app.MapControllerRoute(
    name: "converter-config",
    pattern: "converter/config/{converterType}",
    defaults: new { controller = "Converter", action = "GetConverterConfig" });

// Rotas específicas por idioma
app.MapControllerRoute(
    name: "converter_localized_specific",
    pattern: "{language:regex(^(pt|en|es)$)}/{converter}",
    defaults: new { controller = "Converter", action = "Index" });

// Rota para home localizada
app.MapControllerRoute(
    name: "home_localized",
    pattern: "{language:regex(^(pt|en|es)$)}",
    defaults: new { controller = "Home", action = "Index" });

app.MapControllerRoute(
    name: "module_endpoint",
    pattern: "modules/{moduleId}",
    defaults: new { controller = "Module", action = "GetModule" });

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

// SEO Routes
app.MapGet("/sitemap.xml", async (ISiteConfigurationService siteConfig) =>
{
    var sitemap = await siteConfig.GenerateSitemapAsync();
    return Results.Content(sitemap, "application/xml");
});

app.MapGet("/robots.txt", async (ISiteConfigurationService siteConfig) =>
{
    var robots = await siteConfig.GenerateRobotsAsync();
    return Results.Content(robots, "text/plain");
});

// Health check endpoint
app.MapGet("/health", () => Results.Ok(new { status = "healthy", timestamp = DateTime.UtcNow }));

// Initialize default data on startup (only in development)
if (app.Environment.IsDevelopment())
{
    using var scope = app.Services.CreateScope();
    var siteConfigService = scope.ServiceProvider.GetRequiredService<ISiteConfigurationService>();
    var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();

    try
    {
        // Verificar se j� existem configura��es
        var languages = new[] { "pt", "en", "es" };
        foreach (var lang in languages)
        {
            var configExists = await siteConfigService.ConfigurationExistsAsync(lang);
            if (!configExists)
            {
                logger.LogInformation("Criando configura��o padr�o para idioma: {Language}", lang);
                _ = await siteConfigService.GetConfigurationAsync(lang); // Isso criar� a configura��o padr�o
            }
        }

        // Inicializar módulos de exemplo
        try
        {
            var moduleService = scope.ServiceProvider.GetRequiredService<IModuleService>();

            // Verificar se já existe módulo de exemplo
            var existingModule = await moduleService.GetModuleConfigAsync("footer-message");
            if (existingModule == null)
            {
                var exampleModule = new ModuleConfig
                {
                    ModuleId = "footer-message",
                    Name = "Módulo de Mensagem do Footer",
                    Url = "https://httpbin.org/html", // URL de exemplo que retorna HTML
                    RequestBy = "footer-message",
                    IsActive = true,
                    CacheMinutes = 10
                };

                await moduleService.SaveModuleConfigAsync(exampleModule);
                logger.LogInformation("Módulo de exemplo criado: {ModuleId}", exampleModule.ModuleId);
            }
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Erro ao inicializar módulos de exemplo");
        }
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "Erro ao inicializar dados padr�o");
    }
}

app.Run();