using Health.Application.Users;

namespace Health.Infrastructure.Users;

public sealed class EfUserRepository(AppDbContext db) : IUserRepository
{
    private readonly AppDbContext _db = db;

    public Task<User?> GetAsync(Guid userId, CancellationToken ct) =>
        _db.Users.FirstOrDefaultAsync(u => u.Id == userId, ct);

    public Task SaveChangesAsync(CancellationToken ct) =>
        _db.SaveChangesAsync(ct);

    public async Task DeleteAccountDataAsync(Guid userId, CancellationToken ct)
    {
        await using var transaction = await _db.Database.BeginTransactionAsync(ct);

        var profile = await _db.DoctorProfiles.FirstOrDefaultAsync(p => p.UserId == userId, ct);
        if (profile?.DoctorId != null)
        {
            await _db.Users.Where(u => u.DoctorId == profile.DoctorId)
                .ExecuteUpdateAsync(u => u.SetProperty(x => x.DoctorId, (Guid?)null), ct);
            await _db.Doctors.Where(d => d.Id == profile.DoctorId).ExecuteDeleteAsync(ct);
        }

        await _db.HealthRecords.Where(r => r.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.MedicationLogs.Where(l => l.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.Medications.Where(m => m.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.DietFoodItems.Where(i => i.DietRecord!.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.DietRecords.Where(d => d.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.ExercisePlanItems.Where(i => i.Plan!.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.ExercisePlans.Where(p => p.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.ReportAnalysisTasks.Where(t => _db.Reports.Any(r => r.Id == t.ReportId && r.UserId == userId)).ExecuteDeleteAsync(ct);
        await _db.Reports.Where(r => r.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.ConversationMessages.Where(m => m.Conversation!.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.Conversations.Where(c => c.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.ConsultationMessages.Where(m => m.Consultation!.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.Consultations.Where(c => c.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.FollowUps.Where(f => f.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.RefreshTokens.Where(t => t.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.DeviceTokens.Where(t => t.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.UserNotifications.Where(n => n.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.NotificationOutbox.Where(n => n.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.NotificationPreferences.Where(p => p.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.HealthArchives.Where(a => a.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.AiWriteCommands.Where(c => c.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.DoctorProfiles.Where(p => p.UserId == userId).ExecuteDeleteAsync(ct);
        await _db.Users.Where(u => u.Id == userId).ExecuteDeleteAsync(ct);

        await transaction.CommitAsync(ct);
    }
}
