using Entities.Contracts;
using Microsoft.EntityFrameworkCore;
using TechHelper.Context;
using TechHelper.Repository;
using SharedDATA.Api;
using Entities.Configuration;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using TechHelper.Features;
using TechHelper.Server.Repositories;
using Microsoft.OpenApi.Models;
using TechHelper.Services.Beta;
using TechHelper.Server.Context;
using TechHelper.Server.Repository;

/// <summary>
/// TechHelper 服务器应用程序的主入口点
/// 配置和启动 ASP.NET Core Web API 应用程序
/// </summary>
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();                                                              // 添加 MVC 控制器服务 (用于 API)

// 2. 数据库服务 (DbContext)
builder.Services.AddDbContext<ApplicationContext>(options =>
	options
	.UseLazyLoadingProxies()
	.UseMySql(
		builder.Configuration.GetConnectionString("XSDB"),
		ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("XSDB"))
	)
).AddUnitOfWork<ApplicationContext>()
.AddCustomRepository<Exam, AssignmentRepository>()
.AddCustomRepository<ExamAttachment, AssignmentAttachmentRepository>()
.AddCustomRepository<ExamQuestion, ExamQuestionRepository>()
.AddCustomRepository<Class, ClassRepository>()
.AddCustomRepository<ClassUser, ClassUserRepository>()
.AddCustomRepository<Question, QuestionRepository>()
.AddCustomRepository<QuestionContext, QuestionContextRepository>()
.AddCustomRepository<Submission, SubmissionRepository>()
.AddCustomRepository<Subject, SubjectRepository>()
.AddCustomRepository<ExamType, ExamTypeRepository>()
.AddCustomRepository<QuestionType, QuestionTypeRepository>()
.AddCustomRepository<User, UserRepository>()
.AddCustomRepository<KeyPoint, KeyPointRepository>()
.AddCustomRepository<Lesson, LessonRepository>()
.AddCustomRepository<Textbook, TextbookRepository>();


builder.Services.AddAutoMapper(typeof(AutoMapperProFile).Assembly);

// 3. 配置服务 (IOptions)
builder.Services.Configure<ApiConfiguration>(builder.Configuration.GetSection("ApiConfiguration"));
builder.Services.Configure<JwtConfiguration>(builder.Configuration.GetSection("JWTSettings"));


// 4. 认证和授权服务 (Identity, JWT, 自定义 Auth)
// 添加 ASP.NET Core Identity (包含默认的 Cookie 认证和授权服务)
builder.Services.AddIdentity<User, IdentityRole<Guid>>(opt =>
{
	opt.User.AllowedUserNameCharacters = "";
	opt.Lockout.AllowedForNewUsers = true;
	opt.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
	opt.Lockout.MaxFailedAccessAttempts = 3;
})
	.AddRoles<IdentityRole<Guid>>()
	.AddEntityFrameworkStores<ApplicationContext>()
	.AddDefaultTokenProviders();
builder.Services.Configure<DataProtectionTokenProviderOptions>(Options =>
{
	Options.TokenLifespan = TimeSpan.FromHours(2);
});


// 添加 JWT Bearer 认证方案
var jwtSettings = builder.Configuration.GetSection("JWTSettings");
builder.Services.AddAuthentication(options =>
{
	options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;             // 设置默认认证方案为 JWT Bearer
	options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;                // 设置默认挑战方案为 JWT Bearer
})
.AddJwtBearer(options =>
{
	options.TokenValidationParameters = new TokenValidationParameters
	{
		ValidateIssuer = true,                                                                          // 验证签发人
		ValidateAudience = true,                                                                        // 验证受众
		ValidateLifetime = true,                                                                        // 验证令牌有效期
		ValidateIssuerSigningKey = true,                                                                // 验证签名密钥
		
		ValidIssuer = jwtSettings["validIssuer"],                                                       // 合法的签发人
		ValidAudience = jwtSettings["validAudience"],                                                   // 合法的受众
		IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["securityKey"])) // 签名密钥
	};
});

builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
builder.Services.AddScoped<IEmailSender, QEmailSender>();
builder.Services.AddScoped<IClassService, ClassService>();
builder.Services.AddScoped<IExamService, ExamService>();
builder.Services.AddScoped<IUserSerivces, UserServices>();
builder.Services.AddScoped<ISubmissionService, SubmissionService>();
builder.Services.AddScoped<ISubmissionDetailService, SubmissionDetailService>();
builder.Services.AddScoped<IExamRepository, ExamRepository>();
builder.Services.AddScoped<ISchoolService, SchoolService>();
builder.Services.AddScoped<IGradeService, GradeService>();
builder.Services.AddScoped<ISubjectService, SubjectService>();
builder.Services.AddScoped<IExamTypeService, ExamTypeService>();
builder.Services.AddScoped<IQuestionTypeService, QuestionTypeService>();
builder.Services.AddScoped<IQuestionService, QuestionService>();
builder.Services.AddScoped<IExamQuestionService, ExamQuestionService>();
builder.Services.AddScoped<IKeyPointService, KeyPointService>();
builder.Services.AddScoped<ILessonService, LessonService>();
builder.Services.AddScoped<ITextbookService, TextbookService>();



builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
	c.SwaggerDoc("v1", new OpenApiInfo { Title = "Your API Name", Version = "v1" });

	c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
	{
		Name = "Authorization",
		Type = SecuritySchemeType.Http,
		Scheme = "bearer",
		BearerFormat = "JWT",
		In = ParameterLocation.Header,
		Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"",
	});

	c.AddSecurityRequirement(new OpenApiSecurityRequirement
	{
		{
			new OpenApiSecurityScheme
			{
				Reference = new OpenApiReference
				{
					Type = ReferenceType.SecurityScheme,
					Id = "Bearer"
				}
			},
			new string[] {}
		}
	});
});

builder.Services.AddCors(options =>
{
	options.AddPolicy("AllowSpecificOrigin",
		builder => builder
			.WithOrigins("https://localhost:7047", "http://localhost:7047", "https://localhost:5001", "http://localhost:5001")
			.AllowAnyHeader()
			.AllowAnyMethod()
			.AllowCredentials());
});

var app = builder.Build();



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

app.UseCors("AllowSpecificOrigin");
app.UseHttpsRedirection();

app.UseAuthorization();

using (var scope = app.Services.CreateScope())
{
	var services = scope.ServiceProvider;
	try
	{
		var roleManager = services.GetRequiredService<RoleManager<IdentityRole<Guid>>>();
		await DbInitializer.SeedRoles(roleManager);
	}
	catch (Exception ex)
	{
		var logger = services.GetRequiredService<ILogger<Program>>();
		logger.LogError(ex, "An error occurred while seeding the database.");
	}
}

app.MapControllers();

app.Run();
