using ElectroShop.DAL.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using System;
using System.Diagnostics;
using System.Linq;

namespace ElectroShop.DAL
{
    public class DbInitializer : IDbInitializer
    {
        private readonly ElectroShopDBContext _context;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly RoleManager<IdentityRole> _roleManager;

        public DbInitializer(
            ElectroShopDBContext context,
            UserManager<ApplicationUser> userManager,
            RoleManager<IdentityRole> roleManager)
        {
            _context = context;
            _userManager = userManager;
            _roleManager = roleManager;
        }

        public void Initialize()
        {

            // Odkomentujeme to zda budeme chtit zmenit DB
            //#if DEBUG
            //            _context.Database.EnsureDeleted();
            //#endif

            //create database schema if none exists
            _context.Database.EnsureCreated();

            InitRole(UserType.Administrator);
            InitRole(UserType.Designer);
            InitRole(UserType.Warehouseman);

            InitUser("admin", "Master1234*", UserType.Administrator);
            InitUser("skladnik", "Master1234*", UserType.Warehouseman);
            InitUser("konstrukter", "Master1234*", UserType.Designer);
        }

        private static readonly Object InitRoleLockObj = new Object();
        private void InitRole(UserType usertype)
        {
            lock (InitRoleLockObj)
            {
                if (!_context.Roles.Any(r => r.Name == Enum.GetName(typeof(UserType), usertype)))
                {
                    var result = _roleManager.CreateAsync(new IdentityRole(Enum.GetName(typeof(UserType), usertype))).Result;
                    var resultSaveCahnges = _context.SaveChangesAsync().Result;
                }
            }
        }

        private static readonly Object InitUserLockObj = new Object();
        private void InitUser(string username, string password, UserType usertype)
        {
            lock (InitUserLockObj)
            {
                if (!_context.Users.Any(u => u.UserName == username))
                {
                    var result = _userManager.CreateAsync(new ApplicationUser { UserName = username, Email = username, EmailConfirmed = true }, password).Result;
                    var resultSaveCahnges = _context.SaveChangesAsync().Result;
                }

                if (_context.Users.Any(u => u.UserName == username))
                {
                    var userAdmin = _userManager.FindByNameAsync(username).Result;
                    if (!_userManager.GetRolesAsync(userAdmin).Result.Any())
                    {
                        var result = _userManager.AddToRoleAsync(userAdmin, (Enum.GetName(typeof(UserType), usertype))).Result;
                        if (!result.Succeeded)
                        {
                            throw new Exception("Adding role to admin user failed.");
                        }
                        var resultSaveCahnges = _context.SaveChangesAsync().Result;
                    }
                }
            }

        }
    }
}