namespace Health.WebApi.Endpoints;

public static class CalendarEndpoints
{
    public static void MapCalendarEndpoints(this WebApplication app)
    {
        app.MapGet("/api/calendar", async (
            int year, int month,
            HttpContext http, AppDbContext db, CancellationToken ct) =>
        {
            var userId = GetUserId(http);
            var start = new DateOnly(year, month, 1);
            var end = start.AddMonths(1);

            // 用药
            var medications = await db.Medications
                .Where(m => m.UserId == userId && m.IsActive && m.TimeOfDay.Count > 0)
                .Select(m => new { m.Id, m.Name, m.TimeOfDay })
                .ToListAsync(ct);

            // 运动
            var plans = await db.ExercisePlans
                .Where(p => p.UserId == userId && p.WeekStartDate < end)
                .Include(p => p.Items)
                .ToListAsync(ct);

            // 健康数据日期
            var healthDates = await db.HealthRecords
                .Where(r => r.UserId == userId
                    && r.RecordedAt >= start.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc)
                    && r.RecordedAt < end.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc))
                .Select(r => DateOnly.FromDateTime(r.RecordedAt))
                .Distinct()
                .ToListAsync(ct);

            // 复查随访
            var followups = await db.FollowUps
                .Where(f => f.UserId == userId
                    && f.ScheduledAt >= start.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc)
                    && f.ScheduledAt < end.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc))
                .Select(f => new { f.Id, f.Title, f.Department,
                    Date = DateOnly.FromDateTime(f.ScheduledAt) })
                .ToListAsync(ct);

            var result = new List<object>();
            for (var d = start; d < end; d = d.AddDays(1))
            {
                var events = new List<string>();
                if (medications.Any()) events.Add("medication");
                if (plans.Any(p => p.Items.Any(i => i.DayOfWeek == (int)d.DayOfWeek && !i.IsRestDay)))
                    events.Add("exercise");
                if (followups.Any(f => f.Date == d)) events.Add("followup");
                if (healthDates.Contains(d)) events.Add("health_record");

                if (events.Count > 0)
                    result.Add(new { date = d.ToString("yyyy-MM-dd"), events });
            }

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

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