using System.Text.Json.Serialization;
using GerbilManagerWebAPI.Endpoints;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.EntityFrameworkCore;
using Scalar.AspNetCore;

var builder = WebApplication.CreateBuilder(args);

builder.AddServiceDefaults();

// LAN reachability: bind on all interfaces (keep the Aspire/launch-assigned port),
// so phones/laptops on the home network can reach the API (trusted LAN, no auth).
var aspnetUrls = Environment.GetEnvironmentVariable("ASPNETCORE_URLS");
if (!string.IsNullOrWhiteSpace(aspnetUrls))
{
    var lanUrls = string.Join(';', aspnetUrls
        .Split(';', StringSplitOptions.RemoveEmptyEntries)
        .Select(u => u.Replace("localhost", "0.0.0.0").Replace("127.0.0.1", "0.0.0.0")));
    builder.WebHost.UseUrls(lanUrls);
}

builder.AddNpgsqlDbContext<ApplicationContext>("gerbilmanager");

// JSON: camelCase property names + enums serialised as their string names (frontend contract).
builder.Services.ConfigureHttpJsonOptions(o =>
{
    o.SerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
    o.SerializerOptions.Converters.Add(new JsonStringEnumConverter());
});

// Permissive CORS for the trusted home LAN (no auth — see board constraint).
const string LanCorsPolicy = "lan";
builder.Services.AddCors(options => options.AddPolicy(LanCorsPolicy, policy =>
    policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()));

// OpenAPI document for the Scalar API reference (Swashbuckle removed).
builder.Services.AddOpenApi();

// FEAT-12a: provider-agnostic AI config (env vars AI__BaseUrl/AI__ApiKey/AI__Model
// or user-secrets — never committed) + typed client for sale-ad generation.
builder.Services.AddOptions<GerbilManagerWebAPI.SaleAd.AiOptions>()
    .BindConfiguration(GerbilManagerWebAPI.SaleAd.AiOptions.SectionName);
builder.Services.AddHttpClient<GerbilManagerWebAPI.SaleAd.SaleAdService>(
    http => http.Timeout = TimeSpan.FromSeconds(60));
// INBOX-2: KI-Antwortentwurf (gleiche AI-Sektion, gleicher Wire-Client).
builder.Services.AddHttpClient<GerbilManagerWebAPI.Inbox.DraftReplyService>(
    http => http.Timeout = TimeSpan.FromSeconds(60));
// FEAT-NAMEGEN: Name suggestions via Gemini (same AI section, same wire client).
builder.Services.AddHttpClient<GerbilManagerWebAPI.Names.NameSuggestionService>(
    http => http.Timeout = TimeSpan.FromSeconds(60));

// INBOX-0: Gmail inbox. App Password encrypted at rest via Data Protection.
// AR-3: persist the key ring so encrypted passwords survive image redeployments.
// In prod the path is mounted to a persistent volume (compose DataProtection__KeyRingPath).
// In dev (Aspire) keys live in the content root — ephemeral, which is fine there.
{
    var keyRingPath = builder.Configuration["DataProtection:KeyRingPath"]
        ?? Path.Combine(builder.Environment.ContentRootPath, ".data-protection-keys");
    Directory.CreateDirectory(keyRingPath);
    builder.Services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(keyRingPath))
        .SetApplicationName("GerbilManager");
}
builder.Services.AddScoped<GerbilManagerWebAPI.Inbox.MailSettingsService>();
builder.Services.AddScoped<GerbilManagerWebAPI.Inbox.IGmailMailReader, GerbilManagerWebAPI.Inbox.GmailMailReader>();
builder.Services.AddScoped<GerbilManagerWebAPI.Inbox.RequestSyncService>();
builder.Services.AddScoped<GerbilManagerWebAPI.Inbox.IGmailMailSender, GerbilManagerWebAPI.Inbox.GmailMailSender>();
builder.Services.AddScoped<GerbilManagerWebAPI.Inbox.SendReplyService>();

var app = builder.Build();

app.MapDefaultEndpoints();

// API reference at /scalar (built on the OpenAPI doc at /openapi/v1.json).
app.MapOpenApi();
app.MapScalarApiReference();

// Apply EF migrations at startup (no-op if schema is current; safe for single-instance deploy).
// Unter "Testing" übersprungen: die Endpoint-Tests laufen auf SQLite in-memory
// (EnsureCreated) — die Npgsql-Migrationen sind dort nicht anwendbar.
if (!app.Environment.IsEnvironment("Testing"))
{
    using var scope = app.Services.CreateScope();
    scope.ServiceProvider.GetRequiredService<ApplicationContext>().Database.Migrate();
}

app.UseCors(LanCorsPolicy);

// Endpoint groups (Minimal API, no controllers).
app.MapGerbilEndpoints();
app.MapLitterEndpoints();
app.MapContactEndpoints();
app.MapEnclosureEndpoints();
app.MapColorVarietyEndpoints();
app.MapHealthRecordEndpoints();
app.MapWeightRecordEndpoints();
app.MapInbreedingEndpoints();
app.MapPhotoEndpoints();
app.MapSaleAdEndpoints();
app.MapImportEndpoints();
app.MapContractEndpoints();
app.MapSettingsEndpoints();
app.MapExportEndpoints();
app.MapCmsEndpoints();
app.MapRequestEndpoints();
app.MapNamesEndpoints();

app.Run();

// Sichtbarer Programmtyp für WebApplicationFactory<Program> (Endpoint-Tests).
public partial class Program { }
