using Common.WebApi.Middlewares;
using Microsoft.OpenApi.Models;
using Modules.Library.Application;
using Modules.Library.Database;
using Modules.Library.WebApi.Models.Views.Anime;
using Modules.Rating.Api;
using Modules.User.Api;
using Modules.User.Application;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI;

var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();



// Add services to the container.
//builder.Services.AddDatabase("mongodb://localhost:27017", "MyBookmarkDb");
//builder.Services.AddRates("mongodb://localhost:27017", "MyBookmarkDb");
builder.Services.AddDatabase(builder.Configuration.GetConnectionString("PostgreSQL"));
builder.Services.AddRates(builder.Configuration.GetConnectionString("PostgreSQL"));

builder.Services.AddApplicationServices();
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

builder.Services.AddAccount(builder.Configuration, "JwtSettings", builder.Configuration.GetConnectionString("PostgreSQL"), "MinIO");

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.Configure<SwaggerGenOptions>(options =>
{
    options.UseAllOfToExtendReferenceSchemas();
    options.UseOneOfForPolymorphism();
    options.SelectSubTypesUsing(baseType =>
    {
        if (baseType == typeof(AnimeItem)) return [typeof(Season), typeof(Episode)];
        return [];
    });

    options.SwaggerDoc("AnimeTitleV1", new OpenApiInfo
    {
        Title = "Title",
        Description = "Description",
        Contact = new OpenApiContact
        {
            Name = "Example Contact",
            Url = new Uri("https://example.com/contact")
        },
        License = new OpenApiLicense
        {
            Name = "Example License",
            Url = new Uri("https://example.com/license")
        },
        Version = "v1"
    });
    options.SwaggerDoc("AnimeTitle1V1", new OpenApiInfo
    {
        Title = "Title1",
        Description = "Description",
        Contact = new OpenApiContact
        {
            Name = "Example Contact",
            Url = new Uri("https://example.com/contact")
        },
        License = new OpenApiLicense
        {
            Name = "Example License",
            Url = new Uri("https://example.com/license")
        },
        Version = "v1"
    });
    /*
    options.SwaggerDoc("AnimeSeasonV1", new OpenApiInfo
    {
        Title = "Season",
        Description = "Description",
        Contact = new OpenApiContact
        {
            Name = "Example Contact",
            Url = new Uri("https://example.com/contact")
        },
        License = new OpenApiLicense
        {
            Name = "Example License",
            Url = new Uri("https://example.com/license")
        },
        Version = "v1"
    });

    options.SwaggerDoc("AnimeEpisodeV1", new OpenApiInfo
    {
        Title = "Episode",
        Description = "Description",
        Contact = new OpenApiContact
        {
            Name = "Example Contact",
            Url = new Uri("https://example.com/contact")
        },
        License = new OpenApiLicense
        {
            Name = "Example License",
            Url = new Uri("https://example.com/license")
        },
        Version = "v1"
    });
    */

    options.SwaggerDoc("GenreV1", new OpenApiInfo
    {
        Title = "Genre",
        Description = "Description",
        Contact = new OpenApiContact
        {
            Name = "Example Contact",
            Url = new Uri("https://example.com/contact")
        },
        License = new OpenApiLicense
        {
            Name = "Example License",
            Url = new Uri("https://example.com/license")
        },
        Version = "v1"
    });

    options.SwaggerDoc("LanguageV1", new OpenApiInfo
    {
        Title = "Language",
        Description = "Description",
        Contact = new OpenApiContact
        {
            Name = "Example Contact",
            Url = new Uri("https://example.com/contact")
        },
        License = new OpenApiLicense
        {
            Name = "Example License",
            Url = new Uri("https://example.com/license")
        },
        Version = "v1"
    });

    options.UseAllOfToExtendReferenceSchemas();
    options.UseOneOfForPolymorphism();
    options.UseAllOfForInheritance();

    //options.MapType<AnimeItem>(() => new OpenApiSchema
    //{
    //    Type = "object",
    //    OneOf =
    //    [
    //        new OpenApiSchema { Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = nameof(Season) }},
    //        new OpenApiSchema { Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = nameof(Episode) }}
    //    ]
    //});

    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer",
        BearerFormat = "JWT",
        In = ParameterLocation.Header,
        Description = "Enter 'Bearer' [space] and then your valid token in the text input below.\r\n\r\nExample: \"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\"",
    });

    options.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            Array.Empty<string>()
        }
    });

}).Configure<SwaggerUIOptions>(options =>
{
    /*
    options.SwaggerEndpoint("MediaContent/Anime/Title/swagger.json", "Anime Title V1");
    //options.SwaggerEndpoint("MediaContent/Anime/Season/swagger.json", "Anime Season V1");
    //options.SwaggerEndpoint("MediaContent/Anime/Episode/swagger.json", "Anime Episode V1");
    options.SwaggerEndpoint("Dictionaries/Genre/swagger.json", "Genre V1");
    options.SwaggerEndpoint("Dictionaries/Language/swagger.json", "Language V1");
    */
    options.SwaggerEndpoint("AnimeTitleV1/swagger.json", "Anime Title V1");
    options.SwaggerEndpoint("AnimeTitle1V1/swagger.json", "Anime Title1 V1");
    //options.SwaggerEndpoint("MediaContent/Anime/Season/swagger.json", "Anime Season V1");
    //options.SwaggerEndpoint("MediaContent/Anime/Episode/swagger.json", "Anime Episode V1");
    options.SwaggerEndpoint("GenreV1/swagger.json", "Genre V1");
    options.SwaggerEndpoint("LanguageV1/swagger.json", "Language V1");
});

var app = builder.Build();

app.UseCors(q => q.AllowAnyHeader().AllowAnyOrigin().AllowAnyMethod()); //??

app.UseMiddleware<ExceptionMiddleware>();

app.MapDefaultEndpoints();


// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

//app.UseHttpsRedirection();

app.UseAuthorization();

app.UseMiddleware<UserMiddleware>();

app.MapControllers();

app.Run();
