using API.Models;
using API.Security;
using Microsoft.AspNetCore.Identity;

namespace API.Services
{
    public class IdentitySeedService(
        UserManager<AppUser> userManager,
        RoleManager<IdentityRole<Guid>> roleManager,
        IConfiguration configuration,
        ILogger<IdentitySeedService> logger)
    {
        public async Task SeedAsync()
        {
            await EnsureRoleExistsAsync(RoleNames.Admin);

            var adminUsers = await userManager.GetUsersInRoleAsync(RoleNames.Admin);
            if (adminUsers.Count > 0)
            {
                logger.LogDebug("Admin-Seed übersprungen: Es existiert bereits ein Admin über Rollen.");
                return;
            }

            var adminUserName = configuration["SeedAdmin:UserName"] ?? "admin";
            var adminPassword = configuration["SeedAdmin:Password"] ?? "HoardPassword";
            var adminEmail = configuration["SeedAdmin:Email"];

            var admin = await userManager.FindByNameAsync(adminUserName);
            if (admin is null)
            {
                admin = new AppUser
                {
                    UserName = adminUserName,
                    Email = string.IsNullOrWhiteSpace(adminEmail) ? null : adminEmail,
                    IsActive = true,
                    MustChangePassword = true,
                    CreatedAt = DateTimeOffset.UtcNow,
                    UpdatedAt = DateTimeOffset.UtcNow
                };

                var createResult = await userManager.CreateAsync(admin, adminPassword);
                if (!createResult.Succeeded)
                {
                    var createErrors = string.Join(", ", createResult.Errors.Select(x => x.Description));
                    logger.LogError("Admin-Seed fehlgeschlagen: {Errors}", createErrors);
                    throw new InvalidOperationException($"Admin-Seed fehlgeschlagen: {createErrors}");
                }
            }

            if (!await userManager.IsInRoleAsync(admin, RoleNames.Admin))
            {
                var roleResult = await userManager.AddToRoleAsync(admin, RoleNames.Admin);
                if (!roleResult.Succeeded)
                {
                    var roleErrors = string.Join(", ", roleResult.Errors.Select(x => x.Description));
                    logger.LogError("Admin-Rollenzuweisung fehlgeschlagen: {Errors}", roleErrors);
                    throw new InvalidOperationException($"Admin-Rollenzuweisung fehlgeschlagen: {roleErrors}");
                }
            }

            logger.LogInformation(
                "Admin-Account wurde geseedet bzw. als Rolle zugewiesen (UserName: {UserName}, Email: {Email}).",
                admin.UserName,
                admin.Email ?? "(keine)");
        }

        private async Task EnsureRoleExistsAsync(string roleName)
        {
            if (await roleManager.RoleExistsAsync(roleName))
            {
                return;
            }

            var createRoleResult = await roleManager.CreateAsync(new IdentityRole<Guid>
            {
                Name = roleName
            });

            if (!createRoleResult.Succeeded)
            {
                var roleErrors = string.Join(", ", createRoleResult.Errors.Select(x => x.Description));
                logger.LogError("Rolle {RoleName} konnte nicht erstellt werden: {Errors}", roleName, roleErrors);
                throw new InvalidOperationException($"Rolle {roleName} konnte nicht erstellt werden: {roleErrors}");
            }
        }
    }
}
