// Copyright © Selmo Technology GmbH. All Rights Reserved

using Microsoft.AspNetCore.Identity;
using SelmoStudio.Hmi.Common.Authentication;
using SelmoStudio.Hmi.Plugin.Model.User;
using SelmoStudio.Hmi.Server.Db.Authentication;
using System.Security.Claims;

namespace SelmoStudio.Hmi.Server.Startup
{
    public static class DefaultDataInitializer
    {
        internal static async Task SeedData(
            UserManager<ApplicationUser> userManager,
        RoleManager<ApplicationRole> roleManager,
        List<HmiUser> hmiUsers)
        {
            try
            {
                SeedRoles(roleManager);
                await SeedUsers(userManager, hmiUsers);

                await SeedClaims(userManager);
            }
            catch (Exception ex)
            {
                //TODO FIX
            }
        }

        private static async Task SeedClaims(UserManager<ApplicationUser> userManager)
        {
            foreach (var user in userManager.Users)
            {
                if (user.UserName.Equals("admin"))
                {
                    var appUser = await userManager.FindByNameAsync(user.UserName);
                    var existingClaims = await userManager.GetClaimsAsync(appUser);

                    if (existingClaims == null || existingClaims.Count == 0)
                    {
                        var claims = await GetClaims();
                        await userManager.AddClaimsAsync(appUser, claims);
                    }
                }
            }
        }

        private static async Task<List<Claim>> GetClaims()
        {
            var claims = new List<Claim>();

            var claim = new Claim(WellKnownClaimTypes.Permission, WellKnownPermissionClaims.SystemManaging);
            claims.Add(claim);

            return claims;
        }

        private static void SeedRoles(RoleManager<ApplicationRole> roleManager)
        {
            CreateRoleIfNotExists(SelmoHmiAuthorizationRole.Admin, roleManager);
        }

        private static void CreateRoleIfNotExists(string roleName,
            RoleManager<ApplicationRole> roleManager)
        {
            if (!roleManager.RoleExistsAsync(roleName).Result)
            {
                ApplicationRole role = new ApplicationRole();
                role.Name = roleName;
                role.NormalizedName = roleName.ToUpper();
                _ = roleManager.CreateAsync(role).Result;
            }
        }

        private static async Task SeedUsers(UserManager<ApplicationUser> userManager, List<HmiUser> users)
        {
#if DEBUG

            var userAdmin = await userManager.FindByNameAsync("admin");

            if (userAdmin == null)
            {
                ApplicationUser user = new ApplicationUser()
                {
                    UserName = "admin",
                    Email = "admin@selmo.com",
                    NormalizedEmail = "ADMIN@SELMO.COM",
                    NormalizedUserName = "ADMIN"
                };

                IdentityResult result = await userManager.CreateAsync(user, "Admin*123");

                if (result.Succeeded)
                {
                    var claims = await GetClaims();
                    await userManager.AddClaimsAsync(user, claims);
                    await userManager.AddToRoleAsync(user, SelmoHmiAuthorizationRole.Admin);
                }
            }
#endif

            await SeedStudioUsers(userManager, users);
        }

        private static async Task SeedStudioUsers(UserManager<ApplicationUser> userManager, List<HmiUser> users)
        {
            if (users == null)
                return;
            foreach (var user in users)
            {
                var foundUser = await userManager.FindByNameAsync(user.UserName);
                if (foundUser == null)
                {
                    ApplicationUser newUser = new ApplicationUser()
                    {
                        UserName = user.UserName,
                        Email = user.Email,
                        NormalizedEmail = user.NormalizedEmail,
                        NormalizedUserName = user.NormalizedUserName,
                    };

                    IdentityResult result = await userManager.CreateAsync(newUser, user.Password);

                    if (result.Succeeded)
                    {
                        var claims = CreateClaimsForUser(user);
                        await userManager.AddClaimsAsync(newUser, claims);
                    }
                }
            }
        }

        private static List<Claim> CreateClaimsForUser(HmiUser user)
        {
            var claims = new List<Claim>();
            foreach (var id in user.Permissions)
            {
                claims.Add(new Claim(WellKnownClaimTypes.Permission, WellKnownPermissions.ToClaimValue(WellknownPermissions.MapFromIdToKey(id))));
            }
            return claims;
        }
    }
}