using FJPSite.Attributes;
using FJPSite.Data;
using FJPSite.Data.Identity;
using FJPSite.Enums;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

namespace FJPSite.Factories.EntitySeeders;

[SeedMigration("20260409010423_CreateIdentity")]
public class IdentitySeederFactory : EntitySeederFactory
{
    private struct UserSeed
    {
        public string Email { get; set; }
        public string Firstname { get; set; }
        public string Surname { get; set; }

        public RoleEnum Role { get; set; }
    }
    private static string DefaultPassword = "Potters144A!";
    private static UserSeed[] Users = [
                new UserSeed {Email = "chris@fjp.com.au", Firstname = "Chris", Surname = "McInnes", Role = RoleEnum.Admin},
                new UserSeed {Email = "kim@fjp.com.au", Firstname = "Kim", Surname = "Fell", Role = RoleEnum.Admin},
                new UserSeed {Email = "amanda@fjp.com.au", Firstname = "Amanda", Surname = "Schenk", Role = RoleEnum.Director},
                new UserSeed {Email = "reception@fjp.com.au", Firstname = "Lucy", Surname = "Fox", Role = RoleEnum.User}
            ];

    private static void SeedRoles(RoleManager<RoleEntity> roleManager)
    {
        foreach (var role in (RoleEnum[])Enum.GetValues(typeof(RoleEnum)))
        {
            var rolename = Enum.GetName(role);
            var roleEntity = roleManager.FindByNameAsync(rolename).Result;
            if (roleEntity == null)
            {
                var result = roleManager.CreateAsync(new RoleEntity { Name = rolename }).Result;
                if (result.Succeeded == false)
                {
                    throw new Exception("Failed while seeding roles in database");
                }
            }
        }
    }

    private static void SeedUsers(UserManager<UserEntity> userManager)
    {
        foreach (UserSeed userSeed in Users)
        {
            var user = userManager.FindByNameAsync(userSeed.Email).Result;
            if (user == null)
            {
                var result = userManager.CreateAsync(new UserEntity()
                {
                    UserName = userSeed.Email,
                    Email = userSeed.Email,
                    Surname = userSeed.Surname,
                    Firstname = userSeed.Firstname,
                    EmailConfirmed = true
                }, DefaultPassword).Result;
                if (result.Succeeded == false)
                {
                    throw new Exception("Failed while seeding users in database");
                }
                user = userManager.FindByNameAsync(userSeed.Email).Result;
                result = userManager.SetLockoutEnabledAsync(user, false).Result;
            }

            if (userManager.IsInRoleAsync(user, Enum.GetName(userSeed.Role)).Result == false)
            {
                var roles = userManager.GetRolesAsync(user).Result;
                userManager.RemoveFromRolesAsync(user, roles).Wait();
                userManager.AddToRoleAsync(user, Enum.GetName(userSeed.Role)).Wait();
            }

        }
    }
    public override void Seed(ApplicationDbContext context)
    {
        var userManager = context.GetService<UserManager<UserEntity>>();
        var roleManager = context.GetService<RoleManager<RoleEntity>>();

        SeedRoles(roleManager);
        SeedUsers(userManager);

        context.SaveChanges();
    }
}
