using Asp.Versioning;
using FluentValidation;
using Hellang.Middleware.ProblemDetails;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.SignalR;
using Microsoft.IdentityModel.Tokens;
using MiningService.API.Application.Behaviors;
using MiningService.API.Extensions;
using MiningService.API.Hubs;
using MiningService.Infrastructure;
using Serilog;
using System.Text;

// EN: Configure Serilog early / VI: Cấu hình Serilog sớm
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateBootstrapLogger();

try
{
    Log.Information("Starting MiningService API / Khởi động MiningService API");

    var builder = WebApplication.CreateBuilder(args);

    // EN: Configure Serilog / VI: Cấu hình Serilog
    builder.Host.UseSerilog((context, services, configuration) => configuration
        .ReadFrom.Configuration(context.Configuration)
        .ReadFrom.Services(services)
        .Enrich.FromLogContext()
        .WriteTo.Console());

    // EN: Add Infrastructure services / VI: Thêm Infrastructure services
    builder.Services.AddInfrastructure(builder.Configuration);

    // EN: Add External Service clients (IAM, Wallet, Social) / VI: Thêm External Service clients
    builder.Services.AddExternalServices(builder.Configuration);

    // EN: Add MediatR with behaviors / VI: Thêm MediatR với behaviors
    builder.Services.AddMediatR(cfg =>
    {
        cfg.RegisterServicesFromAssemblyContaining<Program>();
        cfg.AddOpenBehavior(typeof(LoggingBehavior<,>));
        cfg.AddOpenBehavior(typeof(ValidatorBehavior<,>));
        cfg.AddOpenBehavior(typeof(TransactionBehavior<,>));
    });

    // EN: Add FluentValidation / VI: Thêm FluentValidation
    builder.Services.AddValidatorsFromAssemblyContaining<Program>();

    // EN: Add JWT Authentication / VI: Thêm JWT Authentication
    builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        var jwtSecret = builder.Configuration["Jwt:Secret"] ?? "your-super-secret-key-min-32-characters-long";
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"] ?? "goodgo-platform",
            ValidAudience = builder.Configuration["Jwt:Audience"] ?? "goodgo-services",
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret))
        };
        
        // EN: Support JWT in SignalR query string / VI: Hỗ trợ JWT trong query string SignalR
        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                var accessToken = context.Request.Query["access_token"];
                var path = context.HttpContext.Request.Path;
                if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/hubs"))
                {
                    context.Token = accessToken;
                }
                return Task.CompletedTask;
            }
        };
    });
    builder.Services.AddAuthorization();

    // EN: Add SignalR for real-time updates / VI: Thêm SignalR cho cập nhật thời gian thực
    builder.Services.AddSignalR(options =>
    {
        options.EnableDetailedErrors = builder.Environment.IsDevelopment();
        options.KeepAliveInterval = TimeSpan.FromSeconds(15);
    });
    builder.Services.AddSingleton<IMiningHubService, MiningHubService>();

    // EN: Add API versioning / VI: Thêm API versioning
    builder.Services.AddApiVersioning(options =>
    {
        options.DefaultApiVersion = new ApiVersion(1, 0);
        options.AssumeDefaultVersionWhenUnspecified = true;
        options.ReportApiVersions = true;
        options.ApiVersionReader = ApiVersionReader.Combine(
            new UrlSegmentApiVersionReader(),
            new HeaderApiVersionReader("X-Api-Version"));
    })
    .AddApiExplorer(options =>
    {
        options.GroupNameFormat = "'v'VVV";
        options.SubstituteApiVersionInUrl = true;
    });

    // EN: Add controllers / VI: Thêm controllers
    builder.Services.AddControllers();

    // EN: Add ProblemDetails middleware (RFC 7807) / VI: Thêm ProblemDetails middleware
    builder.Services.AddProblemDetails(options =>
    {
        options.IncludeExceptionDetails = (ctx, ex) =>
            builder.Environment.IsDevelopment();
    });

    // EN: Add Swagger with JWT Bearer / VI: Thêm Swagger với JWT Bearer
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen(options =>
    {
        options.SwaggerDoc("v1", new()
        {
            Title = "MiningService API",
            Version = "v1",
            Description = "Pi Network-style Point Mining Service / Dịch vụ đào điểm kiểu Pi Network"
        });
        
        // EN: Add JWT Bearer security definition / VI: Thêm định nghĩa bảo mật JWT Bearer
        options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
        {
            Description = "JWT Authorization header. Example: \"Bearer {token}\"",
            Name = "Authorization",
            In = Microsoft.OpenApi.Models.ParameterLocation.Header,
            Type = Microsoft.OpenApi.Models.SecuritySchemeType.Http,
            Scheme = "bearer",
            BearerFormat = "JWT"
        });
        
        options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
        {
            {
                new Microsoft.OpenApi.Models.OpenApiSecurityScheme
                {
                    Reference = new Microsoft.OpenApi.Models.OpenApiReference
                    {
                        Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
                        Id = "Bearer"
                    }
                },
                Array.Empty<string>()
            }
        });
    });

    // EN: Add health checks / VI: Thêm health checks
    builder.Services.AddHealthChecks()
        .AddNpgSql(
            builder.Configuration.GetConnectionString("DefaultConnection")
                ?? builder.Configuration["DATABASE_URL"]
                ?? "",
            name: "postgresql",
            tags: ["db", "postgresql"]);

    // EN: Add CORS / VI: Thêm CORS
    builder.Services.AddCors(options =>
    {
        options.AddDefaultPolicy(policy =>
        {
            policy.WithOrigins(
                    builder.Configuration.GetSection("AllowedOrigins").Get<string[]>() 
                    ?? ["http://localhost:3000", "http://localhost:5173"])
                  .AllowAnyMethod()
                  .AllowAnyHeader()
                  .AllowCredentials(); // EN: Required for SignalR / VI: Bắt buộc cho SignalR
        });
    });

    var app = builder.Build();

    // EN: Configure middleware pipeline / VI: Cấu hình middleware pipeline
    app.UseSerilogRequestLogging();
    app.UseProblemDetails();

    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "MiningService API v1");
            c.RoutePrefix = "swagger";
        });
    }

    app.UseCors();
    app.UseRouting();
    
    // EN: Add Authentication & Authorization middleware / VI: Thêm middleware xác thực & phân quyền
    app.UseAuthentication();
    app.UseAuthorization();

    // EN: Map health check endpoints / VI: Map health check endpoints
    app.MapHealthChecks("/health");
    app.MapHealthChecks("/health/live", new()
    {
        Predicate = _ => false // EN: Just checks app is running / VI: Chỉ kiểm tra app đang chạy
    });
    app.MapHealthChecks("/health/ready");

    // EN: Map controllers / VI: Map controllers
    app.MapControllers();
    
    // EN: Map SignalR Hub / VI: Map SignalR Hub
    app.MapHub<MiningHub>("/hubs/mining");

    // EN: Run the application / VI: Chạy ứng dụng
    app.Run();
}
catch (Exception ex)
{
    Log.Fatal(ex, "Application terminated unexpectedly / Ứng dụng kết thúc bất ngờ");
    throw;
}
finally
{
    Log.CloseAndFlush();
}

// EN: Make Program class accessible for integration tests
// VI: Làm cho class Program có thể truy cập cho integration tests
public partial class Program { }

