using Microsoft.EntityFrameworkCore; using FutureMailAPI.Data; using FutureMailAPI.Models; using FutureMailAPI.DTOs; namespace FutureMailAPI.Services { public class TimeCapsuleService : ITimeCapsuleService { private readonly FutureMailDbContext _context; public TimeCapsuleService(FutureMailDbContext context) { _context = context; } public async Task> CreateTimeCapsuleAsync(int userId, TimeCapsuleCreateDto createDto) { // 检查邮件是否存在且属于当前用户 var mail = await _context.SentMails .FirstOrDefaultAsync(m => m.Id == createDto.SentMailId && m.SenderId == userId); if (mail == null) { return ApiResponse.ErrorResult("邮件不存在或无权限"); } // 检查是否已存在时间胶囊 var existingCapsule = await _context.TimeCapsules .FirstOrDefaultAsync(tc => tc.SentMailId == createDto.SentMailId); if (existingCapsule != null) { return ApiResponse.ErrorResult("该邮件已创建时间胶囊"); } // 创建时间胶囊 var timeCapsule = new TimeCapsule { UserId = userId, SentMailId = createDto.SentMailId, PositionX = createDto.PositionX, PositionY = createDto.PositionY, PositionZ = createDto.PositionZ, Size = createDto.Size, Color = createDto.Color, Opacity = createDto.Opacity, Rotation = createDto.Rotation, Status = 1, // 漂浮中 Type = createDto.Type }; _context.TimeCapsules.Add(timeCapsule); await _context.SaveChangesAsync(); var capsuleResponse = await GetTimeCapsuleWithDetailsAsync(timeCapsule.Id); return ApiResponse.SuccessResult(capsuleResponse, "时间胶囊创建成功"); } public async Task>> GetTimeCapsulesAsync(int userId, TimeCapsuleListQueryDto queryDto) { var query = _context.TimeCapsules .Where(tc => tc.UserId == userId) .Include(tc => tc.User) .Include(tc => tc.SentMail) .AsQueryable(); // 应用筛选条件 if (queryDto.Status.HasValue) { query = query.Where(tc => tc.Status == queryDto.Status.Value); } if (queryDto.Type.HasValue) { query = query.Where(tc => tc.Type == queryDto.Type.Value); } if (queryDto.IncludeExpired.HasValue && !queryDto.IncludeExpired.Value) { query = query.Where(tc => tc.SentMail.DeliveryTime > DateTime.UtcNow); } // 排序 query = query.OrderByDescending(tc => tc.CreatedAt); // 分页 var totalCount = await query.CountAsync(); var capsules = await query .Skip((queryDto.PageIndex - 1) * queryDto.PageSize) .Take(queryDto.PageSize) .ToListAsync(); var capsuleDtos = capsules.Select(MapToTimeCapsuleResponseDto).ToList(); var pagedResponse = new PagedResponse( capsuleDtos, queryDto.PageIndex, queryDto.PageSize, totalCount); return ApiResponse>.SuccessResult(pagedResponse); } public async Task> GetTimeCapsuleByIdAsync(int userId, int capsuleId) { var timeCapsule = await _context.TimeCapsules .Include(tc => tc.User) .Include(tc => tc.SentMail) .FirstOrDefaultAsync(tc => tc.Id == capsuleId && tc.UserId == userId); if (timeCapsule == null) { return ApiResponse.ErrorResult("时间胶囊不存在"); } var capsuleDto = MapToTimeCapsuleResponseDto(timeCapsule); return ApiResponse.SuccessResult(capsuleDto); } public async Task> UpdateTimeCapsuleAsync(int userId, int capsuleId, TimeCapsuleUpdateDto updateDto) { var timeCapsule = await _context.TimeCapsules .FirstOrDefaultAsync(tc => tc.Id == capsuleId && tc.UserId == userId); if (timeCapsule == null) { return ApiResponse.ErrorResult("时间胶囊不存在"); } // 检查胶囊是否已开启,已开启的胶囊不能修改 if (timeCapsule.Status >= 3) { return ApiResponse.ErrorResult("已开启的时间胶囊不能修改"); } // 更新胶囊信息 if (updateDto.PositionX.HasValue) { timeCapsule.PositionX = updateDto.PositionX.Value; } if (updateDto.PositionY.HasValue) { timeCapsule.PositionY = updateDto.PositionY.Value; } if (updateDto.PositionZ.HasValue) { timeCapsule.PositionZ = updateDto.PositionZ.Value; } if (updateDto.Size.HasValue) { timeCapsule.Size = updateDto.Size.Value; } if (updateDto.Color != null) { timeCapsule.Color = updateDto.Color; } if (updateDto.Opacity.HasValue) { timeCapsule.Opacity = updateDto.Opacity.Value; } if (updateDto.Rotation.HasValue) { timeCapsule.Rotation = updateDto.Rotation.Value; } await _context.SaveChangesAsync(); var capsuleResponse = await GetTimeCapsuleWithDetailsAsync(timeCapsule.Id); return ApiResponse.SuccessResult(capsuleResponse, "时间胶囊更新成功"); } public async Task> DeleteTimeCapsuleAsync(int userId, int capsuleId) { var timeCapsule = await _context.TimeCapsules .FirstOrDefaultAsync(tc => tc.Id == capsuleId && tc.UserId == userId); if (timeCapsule == null) { return ApiResponse.ErrorResult("时间胶囊不存在"); } // 检查胶囊是否已开启,已开启的胶囊不能删除 if (timeCapsule.Status >= 3) { return ApiResponse.ErrorResult("已开启的时间胶囊不能删除"); } // 删除时间胶囊 _context.TimeCapsules.Remove(timeCapsule); await _context.SaveChangesAsync(); return ApiResponse.SuccessResult(true, "时间胶囊删除成功"); } public async Task>> GetPublicTimeCapsulesAsync(TimeCapsuleListQueryDto queryDto) { var query = _context.TimeCapsules .Where(tc => tc.SentMail.RecipientType == 2) // 公开时间胶囊 .Include(tc => tc.User) .Include(tc => tc.SentMail) .AsQueryable(); // 应用筛选条件 if (queryDto.Status.HasValue) { query = query.Where(tc => tc.Status == queryDto.Status.Value); } if (queryDto.Type.HasValue) { query = query.Where(tc => tc.Type == queryDto.Type.Value); } if (queryDto.IncludeExpired.HasValue && !queryDto.IncludeExpired.Value) { query = query.Where(tc => tc.SentMail.DeliveryTime > DateTime.UtcNow); } // 排序 query = query.OrderByDescending(tc => tc.CreatedAt); // 分页 var totalCount = await query.CountAsync(); var capsules = await query .Skip((queryDto.PageIndex - 1) * queryDto.PageSize) .Take(queryDto.PageSize) .ToListAsync(); var capsuleDtos = capsules.Select(MapToTimeCapsuleResponseDto).ToList(); var pagedResponse = new PagedResponse( capsuleDtos, queryDto.PageIndex, queryDto.PageSize, totalCount); return ApiResponse>.SuccessResult(pagedResponse); } public async Task> ClaimPublicCapsuleAsync(int userId, int capsuleId) { var timeCapsule = await _context.TimeCapsules .Include(tc => tc.SentMail) .FirstOrDefaultAsync(tc => tc.Id == capsuleId && tc.SentMail.RecipientType == 2); if (timeCapsule == null) { return ApiResponse.ErrorResult("时间胶囊不存在或不是公开胶囊"); } // 检查胶囊是否已开启 if (timeCapsule.Status >= 3) { return ApiResponse.ErrorResult("时间胶囊已开启"); } // 检查是否已认领 var existingReceivedMail = await _context.ReceivedMails .FirstOrDefaultAsync(rm => rm.SentMailId == timeCapsule.SentMailId && rm.RecipientId == userId); if (existingReceivedMail != null) { return ApiResponse.ErrorResult("您已认领此时间胶囊"); } // 创建接收邮件记录 var receivedMail = new ReceivedMail { SentMailId = timeCapsule.SentMailId, RecipientId = userId, ReceivedAt = DateTime.UtcNow }; _context.ReceivedMails.Add(receivedMail); await _context.SaveChangesAsync(); var capsuleResponse = await GetTimeCapsuleWithDetailsAsync(timeCapsule.Id); return ApiResponse.SuccessResult(capsuleResponse, "时间胶囊认领成功"); } public async Task> GetTimeCapsuleViewAsync(int userId) { // 获取用户的所有时间胶囊 var capsules = await _context.TimeCapsules .Where(tc => tc.UserId == userId) .Include(tc => tc.SentMail) .ToListAsync(); // 转换为视图DTO var capsuleViews = capsules.Select(capsule => { var totalDays = (capsule.SentMail.DeliveryTime - capsule.SentMail.SentAt).TotalDays; var elapsedDays = (DateTime.UtcNow - capsule.SentMail.SentAt).TotalDays; var progress = totalDays > 0 ? Math.Min(1, elapsedDays / totalDays) : 0; return new TimeCapsuleViewDto { CapsuleId = capsule.Id, MailId = capsule.SentMailId, Title = capsule.SentMail.Title, SendTime = capsule.SentMail.SentAt, DeliveryTime = capsule.SentMail.DeliveryTime, Progress = progress, Position = new TimeCapsulePosition { X = capsule.PositionX, Y = capsule.PositionY, Z = capsule.PositionZ }, Style = capsule.Color ?? "#FFFFFF", GlowIntensity = capsule.Status == 1 ? 0.8 : 0.3 // 漂浮中的胶囊发光更亮 }; }).ToList(); // 获取用户偏好设置(如果有) var user = await _context.Users.FindAsync(userId); var scene = user?.PreferredScene ?? "SPACE"; var background = user?.PreferredBackground ?? "default"; var viewResponse = new TimeCapsuleViewResponseDto { Capsules = capsuleViews, Scene = scene, Background = background }; return ApiResponse.SuccessResult(viewResponse); } public async Task> UpdateTimeCapsuleStyleAsync(int userId, int capsuleId, TimeCapsuleStyleUpdateDto updateDto) { var timeCapsule = await _context.TimeCapsules .FirstOrDefaultAsync(tc => tc.Id == capsuleId && tc.UserId == userId); if (timeCapsule == null) { return ApiResponse.ErrorResult("时间胶囊不存在"); } // 检查胶囊是否已开启,已开启的胶囊不能修改 if (timeCapsule.Status >= 3) { return ApiResponse.ErrorResult("已开启的时间胶囊不能修改"); } // 更新胶囊样式 timeCapsule.Color = updateDto.Style; if (updateDto.GlowIntensity.HasValue) { // 将发光强度转换为透明度(反向关系) timeCapsule.Opacity = 1.0 - (updateDto.GlowIntensity.Value * 0.5); } await _context.SaveChangesAsync(); var capsuleResponse = await GetTimeCapsuleWithDetailsAsync(timeCapsule.Id); return ApiResponse.SuccessResult(capsuleResponse, "时间胶囊样式更新成功"); } private async Task GetTimeCapsuleWithDetailsAsync(int capsuleId) { var timeCapsule = await _context.TimeCapsules .Include(tc => tc.User) .Include(tc => tc.SentMail) .FirstOrDefaultAsync(tc => tc.Id == capsuleId); return MapToTimeCapsuleResponseDto(timeCapsule!); } private static TimeCapsuleResponseDto MapToTimeCapsuleResponseDto(TimeCapsule timeCapsule) { var daysUntilDelivery = (int)(timeCapsule.SentMail.DeliveryTime - DateTime.UtcNow).TotalDays; var distanceFromNow = CalculateDistanceFromNow(daysUntilDelivery); return new TimeCapsuleResponseDto { Id = timeCapsule.Id, UserId = timeCapsule.UserId, SentMailId = timeCapsule.SentMailId, MailTitle = timeCapsule.SentMail.Title, PositionX = timeCapsule.PositionX, PositionY = timeCapsule.PositionY, PositionZ = timeCapsule.PositionZ, Size = timeCapsule.Size, Color = timeCapsule.Color, Opacity = timeCapsule.Opacity, Rotation = timeCapsule.Rotation, Status = timeCapsule.Status, StatusText = GetStatusText(timeCapsule.Status), Type = timeCapsule.Type, TypeText = GetTypeText(timeCapsule.Type), CreatedAt = timeCapsule.CreatedAt, DeliveryTime = timeCapsule.SentMail.DeliveryTime, DaysUntilDelivery = daysUntilDelivery, DistanceFromNow = distanceFromNow }; } private static string GetStatusText(int status) { return status switch { 0 => "未激活", 1 => "漂浮中", 2 => "即将到达", 3 => "已开启", _ => "未知" }; } private static string GetTypeText(int type) { return type switch { 0 => "普通", 1 => "特殊", 2 => "限时", _ => "未知" }; } private static double CalculateDistanceFromNow(int daysUntilDelivery) { // 简单的距离计算,可以根据需要调整 // 距离"现在"越远,距离值越大 return Math.Max(1, daysUntilDelivery / 30.0); // 以月为单位 } } }