namespace Health.WebApi.Endpoints;

/// <summary>
/// 健康数据 API 端点
/// </summary>
public static class HealthEndpoints
{
    public static void MapHealthEndpoints(this WebApplication app)
    {
        var group = app.MapGroup("/api/health-records").RequireAuthorization();

        // 查询健康记录
        group.MapGet("/", async (
            string? type, int? days,
            HttpContext http, AppDbContext db, CancellationToken ct) =>
        {
            var userId = GetUserId(http);
            var query = db.HealthRecords.Where(r => r.UserId == userId);

            if (!string.IsNullOrEmpty(type) && Enum.TryParse<HealthMetricType>(type, ignoreCase: true, out var mt))
                query = query.Where(r => r.MetricType == mt);

            if (days.HasValue)
                query = query.Where(r => r.RecordedAt >= DateTime.UtcNow.AddDays(-days.Value));

            var records = await query.OrderByDescending(r => r.RecordedAt).Take(100)
                .Select(r => new
                {
                    r.Id, Type = r.MetricType.ToString(), r.Systolic, r.Diastolic, r.Value, r.Unit,
                    Source = r.Source.ToString(), r.IsAbnormal, r.RecordedAt
                }).ToListAsync(ct);

            return Results.Ok(new { code = 0, data = records, message = (string?)null });
        });

        // 新增健康记录
        group.MapPost("/", async (CreateHealthRecordRequest req, HttpContext http, AppDbContext db, CancellationToken ct) =>
        {
            var userId = GetUserId(http);
            var record = new HealthRecord
            {
                Id = Guid.NewGuid(), UserId = userId, MetricType = req.Type,
                Systolic = req.Systolic, Diastolic = req.Diastolic, Value = req.Value,
                Unit = req.Unit, Source = req.Source, RecordedAt = req.RecordedAt ?? DateTime.UtcNow,
                IsAbnormal = CheckAbnormal(req),
            };
            db.HealthRecords.Add(record);
            await db.SaveChangesAsync(ct);

            return Results.Ok(new { code = 0, data = new { record.Id }, message = (string?)null });
        });

        // 修改健康记录
        group.MapPut("/{id:guid}", async (Guid id, CreateHealthRecordRequest req, HttpContext http, AppDbContext db, CancellationToken ct) =>
        {
            var userId = GetUserId(http);
            var record = await db.HealthRecords.FirstOrDefaultAsync(r => r.Id == id && r.UserId == userId, ct);
            if (record == null) return Results.Ok(new { code = 40004, data = (object?)null, message = "记录不存在" });

            record.Systolic = req.Systolic;
            record.Diastolic = req.Diastolic;
            record.Value = req.Value;
            record.Unit = req.Unit;
            record.RecordedAt = req.RecordedAt ?? record.RecordedAt;
            record.IsAbnormal = CheckAbnormal(req);
            await db.SaveChangesAsync(ct);

            return Results.Ok(new { code = 0, data = new { success = true }, message = (string?)null });
        });

        // 获取各指标最新值
        group.MapGet("/latest", async (HttpContext http, AppDbContext db, CancellationToken ct) =>
        {
            var userId = GetUserId(http);
            var types = new[] { HealthMetricType.BloodPressure, HealthMetricType.HeartRate, HealthMetricType.Glucose, HealthMetricType.SpO2, HealthMetricType.Weight };
            var result = new Dictionary<string, object?>();

            foreach (var t in types)
            {
                var latest = await db.HealthRecords
                    .Where(r => r.UserId == userId && r.MetricType == t)
                    .OrderByDescending(r => r.RecordedAt)
                    .FirstOrDefaultAsync(ct);

                result[t.ToString()] = latest == null ? null : new
                {
                    latest.Systolic, latest.Diastolic, latest.Value, latest.Unit, latest.RecordedAt
                };
            }

            return Results.Ok(new { code = 0, data = result, message = (string?)null });
        });

        // 趋势数据
        group.MapGet("/trend", async (string type, int period, HttpContext http, AppDbContext db, CancellationToken ct) =>
        {
            var userId = GetUserId(http);
            if (!Enum.TryParse<HealthMetricType>(type, ignoreCase: true, out var mt))
                return Results.Ok(new { code = 40001, data = (object?)null, message = "不支持的指标类型" });

            var days = period switch { 7 => 7, 30 => 30, 90 => 90, _ => 7 };
            var records = await db.HealthRecords
                .Where(r => r.UserId == userId && r.MetricType == mt && r.RecordedAt >= DateTime.UtcNow.AddDays(-days))
                .OrderBy(r => r.RecordedAt)
                .Select(r => new { r.Id, r.Systolic, r.Diastolic, r.Value, r.IsAbnormal, r.RecordedAt })
                .ToListAsync(ct);

            return Results.Ok(new { code = 0, data = records, message = (string?)null });
        });
    }

    private static bool CheckAbnormal(CreateHealthRecordRequest req) => req.Type switch
    {
        HealthMetricType.BloodPressure => req.Systolic >= 140 || req.Diastolic >= 90 || req.Systolic <= 89 || req.Diastolic <= 59,
        HealthMetricType.HeartRate => req.Value > 100 || req.Value < 60,
        HealthMetricType.Glucose => req.Value >= 7.0m || req.Value <= 3.8m,
        HealthMetricType.SpO2 => req.Value <= 94,
        _ => false
    };

    private static Guid GetUserId(HttpContext http) =>
        Guid.TryParse(http.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value, out var id) ? id : Guid.Empty;
}

public sealed class CreateHealthRecordRequest
{
    public HealthMetricType Type { get; init; }
    public int? Systolic { get; init; }
    public int? Diastolic { get; init; }
    public decimal? Value { get; init; }
    public string? Unit { get; init; }
    public HealthRecordSource Source { get; init; }
    public DateTime? RecordedAt { get; init; }
}
