// src/Webshop.Application/Services/Customers/CustomerService.cs using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using System.Threading.Tasks; using Webshop.Application.DTOs; // CustomerDto using Webshop.Application.DTOs.Auth; // ChangePasswordRequestDto using Webshop.Application.DTOs.Customers; // UpdateCustomerProfileDto using Webshop.Domain.Entities; // Customer Entity using Webshop.Domain.Interfaces; // ICustomerRepository using Webshop.Domain.Identity; // Für ApplicationUser using System.Linq; // Für Select using System.Collections.Generic; // Für IEnumerable using System.Web; using Resend; using Microsoft.Extensions.Configuration; using System.Net.Mail; namespace Webshop.Application.Services.Customers { public class CustomerService : ICustomerService { private readonly ICustomerRepository _customerRepository; private readonly UserManager _userManager; private readonly IConfiguration _configuration; // << NEU: Für BaseUrl >> private readonly IResend _resend; // << NEU >> public CustomerService( ICustomerRepository customerRepository, UserManager userManager, IConfiguration configuration, // Im Konstruktor injizieren IResend resend) // Im Konstruktor injizieren { _customerRepository = customerRepository; _userManager = userManager; _configuration = configuration; // Im Konstruktor initialisieren _resend = resend; // Im Konstruktor initialisieren } public async Task GetMyProfileAsync(string userId) { var customer = await _customerRepository.GetByUserIdAsync(userId); if (customer == null) return null; var identityUser = await _userManager.FindByIdAsync(userId); if (identityUser == null) return null; return new CustomerDto { Id = customer.Id, UserId = customer.AspNetUserId, FirstName = customer.FirstName, LastName = customer.LastName, Email = identityUser.Email ?? string.Empty, // E-Mail vom ApplicationUser PhoneNumber = identityUser.PhoneNumber, // Telefonnummer vom ApplicationUser DefaultShippingAddressId = customer.DefaultShippingAddressId, DefaultBillingAddressId = customer.DefaultBillingAddressId }; } public async Task<(bool Success, string ErrorMessage)> ChangePasswordAsync(string userId, ChangePasswordRequestDto request) { var user = await _userManager.FindByIdAsync(userId); if (user == null) return (false, "Benutzer nicht gefunden."); var result = await _userManager.ChangePasswordAsync(user, request.OldPassword, request.NewPassword); if (!result.Succeeded) { var errors = string.Join(" ", result.Errors.Select(e => e.Description)); return (false, errors); } return (true, "Passwort erfolgreich geändert."); } // << NEUE IMPLEMENTIERUNG: UpdateMyProfileAsync verarbeitet alle Felder >> public async Task<(bool Success, string ErrorMessage)> UpdateMyProfileAsync(string userId, UpdateCustomerDto profileDto) { var customer = await _customerRepository.GetByUserIdAsync(userId); if (customer == null) return (false, "Kundenprofil nicht gefunden."); var identityUser = await _userManager.FindByIdAsync(userId); if (identityUser == null) return (false, "Benutzerkonto nicht gefunden."); // 1. Aktuelles Passwort prüfen if (!await _userManager.CheckPasswordAsync(identityUser, profileDto.CurrentPassword)) { return (false, "Falsches aktuelles Passwort zur Bestätigung."); } // 2. Felder der Customer-Entität aktualisieren (FirstName, LastName, DEFAULT ADDRESS IDs) customer.FirstName = profileDto.FirstName; customer.LastName = profileDto.LastName; // << NEU: DEFAULT ADDRESS IDs aktualisieren >> customer.DefaultShippingAddressId = profileDto.DefaultShippingAddressId; customer.DefaultBillingAddressId = profileDto.DefaultBillingAddressId; // -- ENDE NEU -- await _customerRepository.UpdateAsync(customer); // 3. Felder des ApplicationUser (IdentityUser) aktualisieren (Email, PhoneNumber) bool identityUserChanged = false; // E-Mail aktualisieren (wenn anders und nicht leer) if (!string.IsNullOrEmpty(profileDto.Email) && identityUser.Email != profileDto.Email) { identityUser.Email = profileDto.Email; identityUser.NormalizedEmail = _userManager.NormalizeEmail(profileDto.Email); identityUser.UserName = profileDto.Email; identityUser.NormalizedUserName = _userManager.NormalizeName(profileDto.Email); identityUserChanged = true; } // Telefonnummer aktualisieren (wenn anders und nicht leer) if (!string.IsNullOrEmpty(profileDto.PhoneNumber) && identityUser.PhoneNumber != profileDto.PhoneNumber) { identityUser.PhoneNumber = profileDto.PhoneNumber; identityUserChanged = true; } if (identityUserChanged) { var updateResult = await _userManager.UpdateAsync(identityUser); if (!updateResult.Succeeded) { var errors = string.Join(" ", updateResult.Errors.Select(e => e.Description)); return (false, $"Fehler beim Aktualisieren der Kontaktdaten: {errors}"); } } return (true, "Profil und Kontaktdaten erfolgreich aktualisiert."); } public async Task<(bool Success, string ErrorMessage)> ChangeEmailAsync(string userId, string newEmail, string currentPassword) { var user = await _userManager.FindByIdAsync(userId); if (user == null) return (false, "Benutzer nicht gefunden."); if (!await _userManager.CheckPasswordAsync(user, currentPassword)) { return (false, "Falsches aktuelles Passwort."); } // Prüfen, ob die neue E-Mail bereits vergeben ist (außer sie ist die aktuelle E-Mail) if (user.Email != newEmail && await _userManager.FindByEmailAsync(newEmail) != null) { return (false, "Die neue E-Mail-Adresse ist bereits registriert."); } var token = await _userManager.GenerateChangeEmailTokenAsync(user, newEmail); var encodedToken = HttpUtility.UrlEncode(token); var baseUrl = _configuration["App:BaseUrl"]; // Link für E-Mail-Bestätigung der Änderung var confirmationLink = $"{baseUrl}/api/v1/auth/change-email-confirm?userId={user.Id}&newEmail={HttpUtility.UrlEncode(newEmail)}&token={encodedToken}"; var message = new EmailMessage(); message.From = "Your Webshop "; // << ANPASSEN >> message.To.Add(newEmail); message.Subject = "Bestätigen Sie Ihre E-Mail-Änderung für Your Webshop"; message.HtmlBody = $@"

E-Mail-Änderung Bestätigung

Sie haben eine Änderung Ihrer E-Mail-Adresse beantragt. Bitte klicken Sie auf den folgenden Link, um dies zu bestätigen:

{confirmationLink}

Wenn Sie diese Änderung nicht angefordert haben, können Sie diese E-Mail ignorieren.

Vielen Dank!

"; await _resend.EmailSendAsync(message); return (true, "Bestätigungs-E-Mail für die E-Mail-Änderung wurde gesendet. Bitte prüfen Sie Ihr Postfach."); } public async Task<(bool Success, string ErrorMessage)> ConfirmEmailChangeAsync(string userId, string newEmail, string token) { var user = await _userManager.FindByIdAsync(userId); if (user == null) return (false, "Benutzer nicht gefunden."); var result = await _userManager.ChangeEmailAsync(user, newEmail, HttpUtility.UrlDecode(token)); if (!result.Succeeded) { var errors = string.Join(" ", result.Errors.Select(e => e.Description)); return (false, $"E-Mail-Änderung konnte nicht bestätigt werden: {errors}"); } // Optional: Bestätigung der Telefonnummer zurücksetzen, wenn E-Mail geändert wurde // user.PhoneNumberConfirmed = false; // await _userManager.UpdateAsync(user); return (true, "E-Mail-Adresse erfolgreich geändert und bestätigt."); } } }