using Fengling.AuthService.Models;
using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
using Fengling.Platform.Infrastructure;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using OpenIddict.Abstractions;

namespace Fengling.AuthService.Data;

public static class SeedData
{
    public static async Task Initialize(IServiceProvider serviceProvider)
    {
        using var scope = serviceProvider.CreateScope();
        var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
        var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
        var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<ApplicationRole>>();
        var applicationManager = scope.ServiceProvider.GetRequiredService<IOpenIddictApplicationManager>();
        var scopeManager = scope.ServiceProvider.GetRequiredService<IOpenIddictScopeManager>();

        var platformDbContext = scope.ServiceProvider.GetRequiredService<PlatformDbContext>();

        var adminTenant = await platformDbContext.InitializeAsync();
        await context.Database.EnsureCreatedAsync();


        var adminRole = await roleManager.FindByNameAsync("Admin");
        if (adminRole == null)
        {
            adminRole = new ApplicationRole
            {
                Name = "Admin",
                DisplayName = "管理员",
                Description = "System administrator",
                TenantId = adminTenant.Id,
                IsSystem = true,
                Permissions = new List<string>
                {
                    "user.manage", "user.view",
                    "role.manage", "role.view",
                    "tenant.manage", "tenant.view",
                    "oauth.manage", "oauth.view",
                    "log.view", "system.config"
                },
                CreatedTime = DateTime.UtcNow
            };
            await roleManager.CreateAsync(adminRole);
        }

        var userRole = await roleManager.FindByNameAsync("User");
        if (userRole == null)
        {
            userRole = new ApplicationRole
            {
                Name = "User",
                DisplayName = "普通用户",
                Description = "Regular user",
                TenantId = adminTenant.Id,
                IsSystem = true,
                Permissions = new List<string> { "user.view" },
                CreatedTime = DateTime.UtcNow
            };
            await roleManager.CreateAsync(userRole);
        }

        var adminUser = await userManager.FindByNameAsync("admin");
        if (adminUser == null)
        {
            adminUser = new ApplicationUser
            {
                UserName = "admin",
                Email = "admin@fengling.local",
                RealName = "系统管理员",
                Phone = "13800138000",
                TenantInfo = new TenantInfo(adminTenant),
                EmailConfirmed = true,
                IsDeleted = false,
                CreatedTime = DateTime.UtcNow
            };

            var result = await userManager.CreateAsync(adminUser, "Admin@123");
            if (result.Succeeded)
            {
                await userManager.AddToRoleAsync(adminUser, "Admin");
            }
        }

        var testUser = await userManager.FindByNameAsync("testuser");
        if (testUser == null)
        {
            testUser = new ApplicationUser
            {
                UserName = "testuser",
                Email = "test@fengling.local",
                RealName = "测试用户",
                Phone = "13900139000",
                TenantInfo = new TenantInfo(adminTenant.Id, adminTenant.TenantCode, adminTenant.Name),
                EmailConfirmed = true,
                IsDeleted = false,
                CreatedTime = DateTime.UtcNow
            };

            var result = await userManager.CreateAsync(testUser, "Test@123");
            if (result.Succeeded)
            {
                await userManager.AddToRoleAsync(testUser, "User");
            }
        }

        var consoleClient = await applicationManager.FindByClientIdAsync("fengling-console");

        if (consoleClient == null)
        {
            var descriptor = new OpenIddictApplicationDescriptor
            {
                ClientId = "fengling-console",
                DisplayName = "Fengling Console",
                Permissions =
                {
                    OpenIddictConstants.Permissions.Endpoints.Authorization,
                    OpenIddictConstants.Permissions.Endpoints.EndSession,
                    OpenIddictConstants.Permissions.Endpoints.Token,
                    OpenIddictConstants.Permissions.Endpoints.Introspection
                }
            };

            foreach (var uri in new[]
                     {
                         "http://localhost:5777/auth/callback",
                         "https://console.fengling.local/auth/callback"
                     })
            {
                descriptor.RedirectUris.Add(new Uri(uri));
            }

            foreach (var uri in new[]
                     {
                         "http://localhost:5777/",
                         "https://console.fengling.local/"
                     })
            {
                descriptor.PostLogoutRedirectUris.Add(new Uri(uri));
            }

            descriptor.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code);

            var scopes = new[]
            {
                OpenIddictConstants.Permissions.Prefixes.Scope + "api",
                OpenIddictConstants.Permissions.Prefixes.Scope + OpenIddictConstants.Scopes.OfflineAccess,
                OpenIddictConstants.Permissions.Prefixes.Scope + OpenIddictConstants.Scopes.OpenId,
                OpenIddictConstants.Permissions.Prefixes.Scope + OpenIddictConstants.Scopes.Profile,
                OpenIddictConstants.Permissions.Prefixes.Scope + OpenIddictConstants.Scopes.Roles,
                OpenIddictConstants.Permissions.Prefixes.Scope + OpenIddictConstants.Scopes.Email
            };

            foreach (var permissionScope in scopes)
            {
                descriptor.Permissions.Add(permissionScope);
            }

            var grantTypes = new[]
            {
                OpenIddictConstants.Permissions.Prefixes.GrantType + OpenIddictConstants.GrantTypes.AuthorizationCode,
                OpenIddictConstants.Permissions.Prefixes.GrantType + OpenIddictConstants.GrantTypes.RefreshToken
            };

            foreach (var grantType in grantTypes)
            {
                descriptor.Permissions.Add(grantType);
            }

            await applicationManager.CreateAsync(descriptor);
        }

        var resourceServerClient = await applicationManager.FindByClientIdAsync("fengling-api");

        if (resourceServerClient == null)
        {
            var resourceDescriptor = new OpenIddictApplicationDescriptor
            {
                ClientId = "fengling-api",
                ClientSecret = "fengling-api-secret",
                DisplayName = "Fengling API",
                Permissions =
                {
                    OpenIddictConstants.Permissions.Endpoints.Introspection
                }
            };

            await applicationManager.CreateAsync(resourceDescriptor);
        }
    }
}