using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Configuration; using System; // Für Uri using System.Linq; using System.Threading.Tasks; using Webshop.Application; // Für ServiceResult using Webshop.Application.DTOs.Auth; using Webshop.Application.DTOs.Customers; using Webshop.Application.Services.Customers.Interfaces; // Namespace korrigiert using Webshop.Application.Services.Public.Interfaces; // WICHTIG: Für IEmailService using Webshop.Domain.Entities; using Webshop.Domain.Identity; using Webshop.Domain.Interfaces; namespace Webshop.Application.Services.Customers { public class CustomerService : ICustomerService { private readonly ICustomerRepository _customerRepository; private readonly UserManager _userManager; private readonly IConfiguration _configuration; private readonly IEmailService _emailService; // NEU: Statt IResend public CustomerService( ICustomerRepository customerRepository, UserManager userManager, IConfiguration configuration, IEmailService emailService) // NEU: Injected { _customerRepository = customerRepository; _userManager = userManager; _configuration = configuration; _emailService = emailService; } public async Task> GetMyProfileAsync(string userId) { var customer = await _customerRepository.GetByUserIdAsync(userId); if (customer == null) return ServiceResult.Fail(ServiceResultType.NotFound, "Kundenprofil nicht gefunden."); var identityUser = await _userManager.FindByIdAsync(userId); if (identityUser == null) return ServiceResult.Fail(ServiceResultType.NotFound, "Benutzerkonto nicht gefunden."); var dto = new CustomerDto { Id = customer.Id, UserId = customer.AspNetUserId, FirstName = customer.FirstName, LastName = customer.LastName, Email = identityUser.Email ?? string.Empty, PhoneNumber = identityUser.PhoneNumber, DefaultShippingAddressId = customer.DefaultShippingAddressId, DefaultBillingAddressId = customer.DefaultBillingAddressId }; return ServiceResult.Ok(dto); } public async Task UpdateMyProfileAsync(string userId, UpdateCustomerDto profileDto) { var customer = await _customerRepository.GetByUserIdAsync(userId); if (customer == null) return ServiceResult.Fail(ServiceResultType.NotFound, "Kundenprofil nicht gefunden."); var identityUser = await _userManager.FindByIdAsync(userId); if (identityUser == null) return ServiceResult.Fail(ServiceResultType.NotFound, "Benutzerkonto nicht gefunden."); // Sicherheitscheck: Passwort prüfen if (!await _userManager.CheckPasswordAsync(identityUser, profileDto.CurrentPassword)) { return ServiceResult.Fail(ServiceResultType.InvalidInput, "Das zur Bestätigung eingegebene Passwort ist falsch."); } // Customer Daten aktualisieren customer.FirstName = profileDto.FirstName; customer.LastName = profileDto.LastName; customer.DefaultShippingAddressId = profileDto.DefaultShippingAddressId; customer.DefaultBillingAddressId = profileDto.DefaultBillingAddressId; await _customerRepository.UpdateAsync(customer); // User Daten (Telefon) aktualisieren if (!string.IsNullOrEmpty(profileDto.PhoneNumber) && identityUser.PhoneNumber != profileDto.PhoneNumber) { identityUser.PhoneNumber = profileDto.PhoneNumber; var updateResult = await _userManager.UpdateAsync(identityUser); if (!updateResult.Succeeded) { var errors = string.Join(" ", updateResult.Errors.Select(e => e.Description)); return ServiceResult.Fail(ServiceResultType.Failure, $"Fehler beim Aktualisieren der Telefonnummer: {errors}"); } } return ServiceResult.Ok(); } public async Task ChangePasswordAsync(string userId, ChangePasswordRequestDto request) { var user = await _userManager.FindByIdAsync(userId); if (user == null) return ServiceResult.Fail(ServiceResultType.NotFound, "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 ServiceResult.Fail(ServiceResultType.InvalidInput, errors); } return ServiceResult.Ok(); } public async Task ChangeEmailAsync(string userId, string newEmail, string currentPassword) { var user = await _userManager.FindByIdAsync(userId); if (user == null) return ServiceResult.Fail(ServiceResultType.NotFound, "Benutzer nicht gefunden."); // Passwort prüfen if (!await _userManager.CheckPasswordAsync(user, currentPassword)) { return ServiceResult.Fail(ServiceResultType.InvalidInput, "Das zur Bestätigung eingegebene Passwort ist falsch."); } // Prüfen, ob neue Email schon existiert (außer es ist die eigene) if (user.Email != newEmail && await _userManager.FindByEmailAsync(newEmail) != null) { return ServiceResult.Fail(ServiceResultType.Conflict, "Die neue E-Mail-Adresse ist bereits registriert."); } // Token generieren var token = await _userManager.GenerateChangeEmailTokenAsync(user, newEmail); var clientUrl = _configuration["App:ClientUrl"]; // Hier stand vorher ! , besser prüfen oder Null-Check // Link bauen (Uri.EscapeDataString ist sicherer in URLs als HttpUtility) var confirmationLink = $"{clientUrl}/confirm-email-change?userId={user.Id}&newEmail={Uri.EscapeDataString(newEmail)}&token={Uri.EscapeDataString(token)}"; // --- REFACTORED: Nutzung des EmailService --- await _emailService.SendEmailChangeConfirmationAsync(newEmail, confirmationLink); // Wir geben die Erfolgsmeldung im Result zurück (passend zu deinem Controller) return ServiceResult.Ok("Bestätigungs-E-Mail wurde an die neue Adresse gesendet. Bitte prüfen Sie Ihr Postfach."); } } }