using System.Text;
using Health.Application.AI;
using Health.Application.Admin;
using Health.Application.Auth;
using Health.Application.Calendars;
using Health.Application.Diets;
using Health.Application.Exercises;
using Health.Application.HealthArchives;
using Health.Application.HealthRecords;
using Health.Application.Medications;
using Health.Application.Maintenance;
using Health.Application.Notifications;
using Health.Application.Reports;
using Health.Application.Users;
using Health.Infrastructure.AI;
using Health.Infrastructure.Admin;
using Health.Infrastructure.Auth;
using Health.Infrastructure.Calendars;
using Health.Infrastructure.Data;
using Health.Infrastructure.Diets;
using Health.Infrastructure.Exercises;
using Health.Infrastructure.HealthArchives;
using Health.Infrastructure.HealthRecords;
using Health.Infrastructure.Medications;
using Health.Infrastructure.Maintenance;
using Health.Infrastructure.Notifications;
using Health.Infrastructure.Reports;
using Health.Infrastructure.Services;
using Health.Infrastructure.Users;
using Health.WebApi.BackgroundServices;
using Health.WebApi.Converters;
using Health.WebApi.Endpoints;
using Health.WebApi.Middleware;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using Microsoft.IdentityModel.Tokens;

// 加载 .env 文件（开发环境）
var envPath = Path.Combine(Directory.GetCurrentDirectory(), "..", "..", ".env");
if (File.Exists(envPath))
{
    foreach (var line in File.ReadAllLines(envPath))
    {
        var trimmed = line.Trim();
        if (string.IsNullOrEmpty(trimmed) || trimmed.StartsWith('#')) continue;
        var eqIdx = trimmed.IndexOf('=');
        if (eqIdx <= 0) continue;
        var key = trimmed[..eqIdx].Trim();
        var value = trimmed[(eqIdx + 1)..].Trim();
        Environment.SetEnvironmentVariable(key, value);
    }
}

var builder = WebApplication.CreateBuilder(args);

if (builder.Environment.IsDevelopment())
{
    builder.Logging.ClearProviders();
    builder.Logging.AddConsole();
    builder.Logging.AddDebug();
    var dataProtectionPath = Path.Combine(Directory.GetCurrentDirectory(), "data-protection-keys");
    Directory.CreateDirectory(dataProtectionPath);
    builder.Services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(dataProtectionPath))
        .SetApplicationName("HealthManager.Development");
}

// ---- JSON 配置（枚举字符串、camelCase、UTC时间统一带Z）----
builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles;
    options.SerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
    options.SerializerOptions.Converters.Add(new UtcDateTimeConverter());
    options.SerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
    options.SerializerOptions.PropertyNameCaseInsensitive = true;
});

// ---- 数据库 ----
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseNpgsql(
        builder.Configuration.GetConnectionString("Default") ?? builder.Configuration["DB_CONNECTION"] ?? "Host=localhost;Database=health_manager;Username=postgres;Password=postgres",
        npgsql => npgsql.MigrationsAssembly(typeof(AppDbContext).Assembly.FullName)));

// ---- JWT 认证 ----
var jwtSecret = builder.Configuration["JWT_SECRET"];
if (string.IsNullOrEmpty(jwtSecret) && !builder.Environment.IsDevelopment())
    throw new InvalidOperationException("JWT_SECRET 环境变量未配置，生产环境必须设置");
jwtSecret ??= "dev-secret-key-change-in-production-min-32-chars!!";
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["JWT_ISSUER"] ?? "health-manager",
            ValidAudience = builder.Configuration["JWT_AUDIENCE"] ?? "health-manager-app",
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret)),
            ClockSkew = TimeSpan.Zero
        };
    });
builder.Services.AddAuthorization();

// ---- 业务服务 ----
builder.Services.AddSingleton<JwtProvider>();
builder.Services.AddSingleton<SmsService>();
builder.Services.AddSingleton<AppleTokenValidator>();  // Apple Sign-In JWT 验证
builder.Services.AddSingleton<PromptManager>();
builder.Services.AddScoped<IAiWriteConfirmationStore, EfAiWriteConfirmationStore>();
builder.Services.AddScoped<IAiToolExecutionService, AiToolExecutionService>();
builder.Services.AddScoped<IAdminService, AdminService>();
builder.Services.AddScoped<IAuthService, AuthService>();
builder.Services.AddScoped<IAiConversationService, AiConversationService>();
builder.Services.AddScoped<IAiConversationRepository, EfAiConversationRepository>();
builder.Services.AddScoped<IPatientContextService, PatientContextService>();
builder.Services.AddScoped<ICalendarService, CalendarService>();
builder.Services.AddScoped<ICalendarRepository, EfCalendarRepository>();
builder.Services.AddScoped<IDietService, DietService>();
builder.Services.AddScoped<IDietRepository, EfDietRepository>();
builder.Services.AddScoped<IDietImageAnalysisCoordinator, DietImageAnalysisCoordinator>();
builder.Services.AddScoped<IDietImageAnalyzer, DietImageAnalyzer>();
builder.Services.AddScoped<IDietImageAnalysisQueue, DietImageAnalysisQueue>();
builder.Services.AddScoped<IAttachmentContextBuilder, AttachmentContextBuilder>();
builder.Services.AddScoped<IExerciseService, ExerciseService>();
builder.Services.AddScoped<IExerciseRepository, EfExerciseRepository>();
builder.Services.AddScoped<IExerciseReminderProducer, ExerciseReminderProducer>();
builder.Services.AddScoped<IHealthArchiveService, HealthArchiveService>();
builder.Services.AddScoped<IHealthArchiveRepository, EfHealthArchiveRepository>();
builder.Services.AddScoped<IHealthRecordService, HealthRecordService>();
builder.Services.AddScoped<IHealthRecordRepository, EfHealthRecordRepository>();
builder.Services.AddScoped<IMedicationService, MedicationService>();
builder.Services.AddScoped<IMedicationRepository, EfMedicationRepository>();
builder.Services.AddScoped<IMedicationReminderScanner, MedicationReminderScanner>();
builder.Services.AddScoped<IMedicationReminderDispatcher, OutboxMedicationReminderDispatcher>();
builder.Services.AddScoped<IMedicationReminderQueue, MedicationReminderQueue>();
builder.Services.AddScoped<IMaintenanceService, MaintenanceService>();
builder.Services.AddScoped<IMaintenanceRepository, EfMaintenanceRepository>();
builder.Services.AddScoped<IInAppNotificationService, InAppNotificationService>();
builder.Services.AddScoped<IInAppNotificationRepository, EfInAppNotificationRepository>();
builder.Services.AddScoped<IUserNotificationProducer, EfUserNotificationProducer>();
builder.Services.AddScoped<INotificationOutboxProcessor, EfNotificationOutboxProcessor>();
builder.Services.AddScoped<IReportService, ReportService>();
builder.Services.AddScoped<IReportRepository, EfReportRepository>();
builder.Services.AddScoped<IReportFileStorage, LocalReportFileStorage>();
builder.Services.AddScoped<IReportAnalysisService, ReportAnalysisService>();
builder.Services.AddScoped<IReportAnalysisQueue, EfReportAnalysisQueue>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IUserRepository, EfUserRepository>();

// ---- AI 客户端（使用 IHttpClientFactory 区分 LLM 和 VLM）----
builder.Services.AddHttpClient<DeepSeekClient>(client =>
{
    client.BaseAddress = new Uri((builder.Configuration["DEEPSEEK_BASE_URL"] ?? "https://api.deepseek.com/v1").TrimEnd('/') + "/");
    client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", builder.Configuration["DEEPSEEK_API_KEY"] ?? "");
    client.Timeout = TimeSpan.FromSeconds(60);
});
builder.Services.AddHttpClient<VisionClient>(client =>
{
    client.BaseAddress = new Uri((builder.Configuration["VLM_BASE_URL"] ?? "https://dashscope.aliyuncs.com/compatible-mode/v1").TrimEnd('/') + "/");
    client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", builder.Configuration["VLM_API_KEY"] ?? "");
    client.Timeout = TimeSpan.FromSeconds(120);
});
builder.Services.AddHttpClient<FastGptKnowledgeClient>(client =>
{
    client.BaseAddress = new Uri((builder.Configuration["FASTGPT_BASE_URL"] ?? "https://cloud.fastgpt.cn/api").TrimEnd('/') + "/");
    client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", builder.Configuration["FASTGPT_API_KEY"] ?? "");
    client.Timeout = TimeSpan.FromSeconds(15);
});

// ---- 后台服务 ----
builder.Services.AddHostedService<MedicationReminderService>();
builder.Services.AddHostedService<ExerciseReminderService>();
builder.Services.AddHostedService<HealthRecordReminderService>();
builder.Services.AddHostedService<MedicationReminderWorker>();
builder.Services.AddHostedService<CleanupService>();
builder.Services.AddHostedService<ReportAnalysisWorker>();
builder.Services.AddHostedService<DietImageAnalysisWorker>();
builder.Services.AddHostedService<NotificationOutboxWorker>();

// ---- OpenAPI ----
builder.Services.AddOpenApi();

// ---- SignalR ----
builder.Services.AddSignalR();

// ---- CORS（SignalR 需要明确 origins + AllowCredentials）----
builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(policy =>
    {
        policy.SetIsOriginAllowed(_ => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials();
    });
});

var app = builder.Build();

// ---- 中间件管道（ExceptionMiddleware 放最前面）----
app.UseMiddleware<ExceptionMiddleware>();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();

// 默认 wwwroot 静态文件（法律文档 H5 页面等）
app.UseDefaultFiles();
app.UseStaticFiles();

var uploadsPath = Path.Combine(Directory.GetCurrentDirectory(), "uploads");
Directory.CreateDirectory(uploadsPath);
app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(uploadsPath),
    RequestPath = "/uploads"
});

if (app.Environment.IsDevelopment())
    app.MapOpenApi();

// ---- 数据库迁移（EF Core Migrations，可用 AUTO_MIGRATE=false 禁用自动迁移）----
using (var scope = app.Services.CreateScope())
{
    var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
    if (app.Configuration.GetValue<bool>("AUTO_MIGRATE", true))
        await db.Database.MigrateAsync();
}

// ---- 注册 API 端点 ----
app.MapAuthEndpoints();
app.MapHealthEndpoints();
app.MapDietEndpoints();
app.MapMedicationEndpoints();
app.MapReportEndpoints();
app.MapConsultationEndpoints();
app.MapExerciseEndpoints();
app.MapUserEndpoints();
app.MapAiChatEndpoints();
app.MapFileEndpoints();
app.MapCalendarEndpoints();
app.MapNotificationEndpoints();
app.MapDoctorEndpoints();
app.MapAdminEndpoints();
app.MapFollowUpEndpoints();

// SignalR Hub
app.MapHub<Health.WebApi.Hubs.ConsultationHub>("/hubs/consultation");

app.Run();
