namespace Netina.Repository.Services;

public class DbInitializerService(
    ApplicationContext context,
    RoleManager<ApplicationRole> roleManager,
    UserManager<ApplicationUser> userManager,
    IOptionsSnapshot<SiteSettings> adminUserSeedOptions,
    ILogger<DbInitializerService> logger,
    IRepositoryWrapper repositoryWrapper)
    : IDbInitializerService
{
    public void Initialize()
    {
        try
        {
            context.Database.Migrate();
            context.Database.ExecuteSqlRaw("CREATE EXTENSION IF NOT EXISTS pg_trgm");
            logger.LogInformation("Migration SUCCESS !!!!");
        }
        catch (Exception e)
        {
            logger.LogError(e, e.Message);
        }
    }

    public async Task SeedDate(bool force = false)
    {
        try
        {
            await SeedRoles();
            var seedAdmin = adminUserSeedOptions.Value.UserSetting;
            var manager = adminUserSeedOptions.Value.Manager;
            var user = await userManager.FindByNameAsync(seedAdmin.Username);
            if (user == null)
            {
                var adminUser = new ApplicationUser
                {
                    UserName = seedAdmin.Username,
                    Email = seedAdmin.Email,
                    EmailConfirmed = true,
                    LockoutEnabled = true,
                    FirstName = seedAdmin.FirstName,
                    LastName = seedAdmin.LastName,
                    Gender = Gender.Male,
                    PhoneNumberConfirmed = true,
                    PhoneNumber = seedAdmin.Phone,
                    BirthDate = DateTime.Now.AddYears(-23)
                };
                var adminUserResult = await userManager.CreateAsync(adminUser, seedAdmin.Password);
                repositoryWrapper.SetRepository<Manager>()
                    .Add(new Manager
                    {
                        UserId = adminUser.Id
                    });
                await repositoryWrapper.SaveChangesAsync(default);
                if (adminUserResult.Succeeded) await userManager.AddToRoleAsync(adminUser, seedAdmin.RoleName);
            }

            var mahanUser = await userManager.FindByNameAsync(manager.Username);
            if (mahanUser == null)
            {
                mahanUser = new ApplicationUser
                {
                    UserName = manager.Username,
                    Email = manager.Email,
                    EmailConfirmed = true,
                    LockoutEnabled = true,
                    FirstName = manager.FirstName,
                    LastName = manager.LastName,
                    Gender = Gender.Male,
                    PhoneNumberConfirmed = true,
                    PhoneNumber = manager.Phone,
                    BirthDate = DateTime.Now.AddYears(-23)
                };
                var adminUserResult = await userManager.CreateAsync(mahanUser, seedAdmin.Password);
                repositoryWrapper.SetRepository<Manager>()
                    .Add(new Manager
                    {
                        UserId = mahanUser.Id
                    });
                await repositoryWrapper.SaveChangesAsync(default);
                if (adminUserResult.Succeeded) await userManager.AddToRoleAsync(mahanUser, "Manager");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }

    public async Task SeedRoles()
    {
        var seedAdmin = adminUserSeedOptions.Value.UserSetting;
        var rootRole = await roleManager.FindByNameAsync(seedAdmin.RoleName);
        if (rootRole == null)
        {
            rootRole = new ApplicationRole
            {
                Name = seedAdmin.RoleName,
                EnglishName = seedAdmin.RoleName,
                Description = "root admin role"
            };
            var adminRoleResult = await roleManager.CreateAsync(rootRole);
            foreach (var claim in ApplicationClaims.AllClaims)
                await roleManager.AddClaimAsync(rootRole, claim);
        }
        else
        {
            foreach (var claim in ApplicationClaims.AllClaims)
            {
                var claims = await roleManager.GetClaimsAsync(rootRole);
                if (claims.FirstOrDefault(c => c.Value == claim.Value) == null)
                    await roleManager.AddClaimAsync(rootRole, claim);
            }
        }

        var managerRole = await roleManager.FindByNameAsync("Manager");
        if (managerRole == null)
        {
            managerRole = new ApplicationRole
            {
                Name = "Manager",
                EnglishName = "Manager",
                PersianName = "مدیریتـــ",
                Description = "admin role"
            };
            var adminRoleResult = await roleManager.CreateAsync(managerRole);
            foreach (var claim in ApplicationClaims.AllClaims)
                await roleManager.AddClaimAsync(managerRole, claim);
        }
        else
        {
            foreach (var claim in ApplicationClaims.AllClaims)
            {
                var claims = await roleManager.GetClaimsAsync(managerRole);
                if (claims.FirstOrDefault(c => c.Value == claim.Value) == null)
                    await roleManager.AddClaimAsync(managerRole, claim);
            }
        }

        var customerRole = await roleManager.FindByNameAsync("Customer");
        if (customerRole == null)
        {
            customerRole = new ApplicationRole
            {
                Name = "Customer",
                PersianName = "مشتری",
                EnglishName = "Customer",

            };
            var customerRoleResult = await roleManager.CreateAsync(customerRole);
            foreach (var claim in ApplicationClaims.CustomerClaims)
                await roleManager.AddClaimAsync(customerRole, claim);
        }
        else
        {
            foreach (var claim in ApplicationClaims.CustomerClaims)
            {
                var claims = await roleManager.GetClaimsAsync(customerRole);
                if (claims.FirstOrDefault(c => c.Value == claim.Value) == null)
                    await roleManager.AddClaimAsync(customerRole, claim);
            }
        }
    }

    public async Task Refactor()
    {
        //var noSlugProducts = await _repositoryWrapper.SetRepository<Product>()
        //    .TableNoTracking
        //    .Where(p => p.Slug == string.Empty)
        //    .ToListAsync();

        //if (noSlugProducts.Count > 0)
        //{
        //    noSlugProducts.ForEach(p =>
        //    {
        //        var slug = StringExtensions.GetSlug(p.PersianName);
        //        p.Slug = slug;
        //    });
        //    _repositoryWrapper.SetRepository<Product>()
        //        .UpdateRange(noSlugProducts);
        //    await _repositoryWrapper.SaveChangesAsync();
        //}

        //var noSlugProductCategories = await _repositoryWrapper.SetRepository<ProductCategory>()
        //    .TableNoTracking
        //    .Where(pc => pc.Slug == string.Empty)
        //    .ToListAsync();
        //if (noSlugProductCategories.Count > 0)
        //{
        //    noSlugProductCategories.ForEach(p =>
        //    {
        //        var slug = StringExtensions.GetSlug(p.Name);
        //        p.Slug = slug;
        //    });
        //    _repositoryWrapper.SetRepository<ProductCategory>()
        //        .UpdateRange(noSlugProductCategories);
        //    await _repositoryWrapper.SaveChangesAsync();
        //}

        //var notSlugBrands = await _repositoryWrapper.SetRepository<Brand>()
        //    .TableNoTracking
        //    .Where(pc => pc.Slug == string.Empty)
        //    .ToListAsync();
        //if (notSlugBrands.Count > 0)
        //{
        //    notSlugBrands.ForEach(p =>
        //    {
        //        var slug = StringExtensions.GetSlug(p.PersianName);
        //        p.Slug = slug;
        //    });
        //    _repositoryWrapper.SetRepository<Brand>()
        //        .UpdateRange(notSlugBrands);
        //    await _repositoryWrapper.SaveChangesAsync();
        //}



        //var noSlugBlogs = await _repositoryWrapper.SetRepository<Blog>()
        //    .TableNoTracking
        //    .Where(pc => pc.Slug == string.Empty)
        //    .ToListAsync();
        //if (noSlugBlogs.Count > 0)
        //{
        //    noSlugBlogs.ForEach(p =>
        //    {
        //        var slug = StringExtensions.GetSlug(p.Title);
        //        p.Slug = slug;
        //    });
        //    _repositoryWrapper.SetRepository<Blog>()
        //        .UpdateRange(noSlugBlogs);
        //    await _repositoryWrapper.SaveChangesAsync();
        //}
        //var noSlugBogCategories = await _repositoryWrapper.SetRepository<BlogCategory>()
        //    .TableNoTracking
        //    .Where(pc => pc.Slug == string.Empty)
        //    .ToListAsync();
        //if (noSlugBogCategories.Count > 0)
        //{
        //    noSlugBogCategories.ForEach(p =>
        //    {
        //        var slug = StringExtensions.GetSlug(p.Name);
        //        p.Slug = slug;
        //    });
        //    _repositoryWrapper.SetRepository<BlogCategory>()
        //        .UpdateRange(noSlugBogCategories);
        //    await _repositoryWrapper.SaveChangesAsync();
        //}
    }
}