// EN: IdentityServer Configuration - Clients, Scopes, Resources
// VI: IdentityServer Configuration - Clients, Scopes, Resources

using Duende.IdentityServer;
using Duende.IdentityServer.Models;

namespace IamService.Infrastructure.IdentityServer;

/// <summary>
/// EN: Static configuration for IdentityServer.
/// VI: Static configuration cho IdentityServer.
/// </summary>
public static class Config
{
    /// <summary>
    /// EN: Identity resources (claims about the user).
    /// VI: Identity resources (claims về user).
    /// </summary>
    public static IEnumerable<IdentityResource> IdentityResources =>
    [
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
        new IdentityResources.Email(),
        new IdentityResource("roles", "User roles", ["role"])
    ];

    /// <summary>
    /// EN: API scopes for protecting APIs.
    /// VI: API scopes để bảo vệ APIs.
    /// </summary>
    public static IEnumerable<ApiScope> ApiScopes =>
    [
        new ApiScope("api", "IAM Service API")
        {
            UserClaims = ["role", "email", "name"]
        }
    ];

    /// <summary>
    /// EN: API resources (logical grouping of scopes).
    /// VI: API resources (nhóm logic của scopes).
    /// </summary>
    public static IEnumerable<ApiResource> ApiResources =>
    [
        new ApiResource("iam-api", "IAM Service API")
        {
            Scopes = { "api" },
            UserClaims = { "role", "email", "name" }
        }
    ];

    /// <summary>
    /// EN: OAuth2/OIDC Clients.
    /// VI: OAuth2/OIDC Clients.
    /// </summary>
    public static IEnumerable<Client> Clients =>
    [
        // EN: Web Application - Authorization Code + PKCE
        // VI: Web Application - Authorization Code + PKCE
        new Client
        {
            ClientId = "web-app",
            ClientName = "Web Application",
            ClientSecrets = { new Secret("web-app-secret".Sha256()) },
            
            AllowedGrantTypes = GrantTypes.Code,
            RequirePkce = true,
            RequireClientSecret = true,
            
            RedirectUris = 
            { 
                "http://localhost:3000/auth/callback",
                "http://localhost:5173/auth/callback",
                "https://localhost:3000/auth/callback"
            },
            PostLogoutRedirectUris = 
            { 
                "http://localhost:3000",
                "http://localhost:5173",
                "https://localhost:3000"
            },
            
            AllowedScopes =
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "roles",
                "api"
            },
            
            AllowOfflineAccess = true,
            AccessTokenLifetime = 900,      // 15 minutes
            RefreshTokenExpiration = TokenExpiration.Sliding,
            SlidingRefreshTokenLifetime = 604800  // 7 days
        },
        
        // EN: Mobile Application - Authorization Code + PKCE (Public Client)
        // VI: Mobile Application - Authorization Code + PKCE (Public Client)
        new Client
        {
            ClientId = "mobile-app",
            ClientName = "Mobile Application",
            
            AllowedGrantTypes = GrantTypes.Code,
            RequirePkce = true,
            RequireClientSecret = false,  // EN: Public client / VI: Public client
            
            RedirectUris = 
            { 
                "com.goodgo.app://oauth/callback",
                "goodgo://auth/callback"
            },
            
            AllowedScopes =
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "roles",
                "api"
            },
            
            AllowOfflineAccess = true,
            AccessTokenLifetime = 900,
            RefreshTokenExpiration = TokenExpiration.Sliding,
            SlidingRefreshTokenLifetime = 604800
        },
        
        // EN: Service-to-Service - Client Credentials
        // VI: Service-to-Service - Client Credentials
        new Client
        {
            ClientId = "service-client",
            ClientName = "Service to Service Client",
            ClientSecrets = { new Secret("service-client-secret".Sha256()) },
            
            AllowedGrantTypes = GrantTypes.ClientCredentials,
            
            AllowedScopes = { "api" }
        },
        
        // EN: Resource Owner Password (for legacy/testing)
        // VI: Resource Owner Password (cho legacy/testing)
        new Client
        {
            ClientId = "password-client",
            ClientName = "Password Grant Client",
            ClientSecrets = { new Secret("password-client-secret".Sha256()) },
            
            AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
            
            AllowedScopes =
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "roles",
                "api"
            },
            
            AllowOfflineAccess = true,
            AccessTokenLifetime = 900,
            RefreshTokenExpiration = TokenExpiration.Sliding,
            SlidingRefreshTokenLifetime = 604800
        },
        
        // EN: Swagger UI Client - for testing via Swagger
        // VI: Swagger UI Client - để test qua Swagger
        new Client
        {
            ClientId = "swagger-ui",
            ClientName = "Swagger UI",
            ClientSecrets = { new Secret("swagger-ui-secret".Sha256()) },
            
            AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
            
            AllowedScopes =
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "roles",
                "api"
            },
            
            AllowOfflineAccess = true,
            AccessTokenLifetime = 3600,  // 1 hour for testing convenience
            RefreshTokenExpiration = TokenExpiration.Sliding,
            SlidingRefreshTokenLifetime = 86400  // 1 day
        }
    ];
}
