using Microsoft.OpenApi.Models;
using Newtonsoft.Json;
using Idoklad.Client;
using Idoklad.Configuration;
using Idoklad.Credentials;
using Idoklad.Infrastructure;
using Idoklad.Services;

var builder = WebApplication.CreateBuilder(args);

// Configuration resolved from environment variables (single shared instance).
var settings = new IdokladSettings();
builder.Services.AddSingleton(settings);

// HttpClient for the iDoklad SDK, managed by IHttpClientFactory (recommended SDK usage).
builder.Services.AddHttpClient(DokladApiFactory.HttpClientName, client =>
{
    client.Timeout = TimeSpan.FromSeconds(settings.RequestTimeoutSeconds);
});

builder.Services.AddHttpContextAccessor();

// Credential resolution + SDK client wiring.
builder.Services.AddScoped<RequestCredentialsProvider>();
builder.Services.AddScoped<DokladApiFactory>();
builder.Services.AddScoped<IdokladApiAccessor>();

// Agenda services.
builder.Services.AddScoped<ContactsService>();
builder.Services.AddScoped<IssuedInvoicesService>();
builder.Services.AddScoped<ReceivedInvoicesService>();
builder.Services.AddScoped<RegistersService>();
builder.Services.AddScoped<AccountService>();

// Use Newtonsoft.Json so request/response binding matches the iDoklad SDK model attributes.
builder.Services
    .AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    });

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo
    {
        Title = settings.AppName,
        Version = settings.AppVersion,
        Description =
            "REST integration with iDoklad built on the official IdokladSdk (.NET) 5.3.0, " +
            "using the OAuth2 client credentials flow.\n\n" +
            "**Credentials.** Every agenda endpoint needs an iDoklad ClientId, ClientSecret and ApplicationId. " +
            "Sensitive values are required in request headers and are never accepted in the query string or body:\n\n" +
            "- `X-ClientId` — iDoklad OAuth2 ClientId\n" +
            "- `X-ClientSecret` — iDoklad OAuth2 ClientSecret (sensitive; TLS only)\n" +
            "- `X-ApplicationId` — iDoklad ApplicationId from the developer portal\n" +
            "- `X-Idoklad-Language` — optional response language (Cz, Sk, En)\n\n" +
            "If a header is omitted, the matching environment default " +
            "(`IDOKLAD_CLIENT_ID`, `IDOKLAD_CLIENT_SECRET`, `IDOKLAD_APPLICATION_ID`) is used. " +
            "If neither a header nor a default is available, the request is rejected with 401.",
    });
    options.OperationFilter<CredentialHeadersOperationFilter>();

    var xmlPath = Path.Combine(AppContext.BaseDirectory, $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml");
    if (File.Exists(xmlPath))
    {
        options.IncludeXmlComments(xmlPath, includeControllerXmlComments: true);
    }
});

var app = builder.Build();

if (!string.IsNullOrWhiteSpace(settings.RootPath))
{
    app.UsePathBase(settings.RootPath);
}

app.UseMiddleware<ExceptionHandlingMiddleware>();

app.UseSwagger();
app.UseSwaggerUI(options =>
{
    options.SwaggerEndpoint("v1/swagger.json", $"{settings.AppName} v1");
});

app.MapControllers();

app.Run();
