# Script PowerShell pour configurer Keycloak pour UnionFlow
# Auteur: UnionFlow Team
# Version: 1.0

Write-Host "🔐 Configuration automatique de Keycloak pour UnionFlow" -ForegroundColor Green
Write-Host "=======================================================" -ForegroundColor Green

# Configuration
$KEYCLOAK_URL = "http://localhost:8180"
$ADMIN_USER = "admin"
$ADMIN_PASSWORD = "admin"
$REALM_NAME = "unionflow"
$CLIENT_ID = "unionflow-server"
$CLIENT_SECRET = "unionflow-secret-2025"

# Fonction pour obtenir le token d'accès admin
function Get-AdminToken {
    Write-Host "📡 Obtention du token d'administration..." -ForegroundColor Yellow
    
    $body = @{
        username = $ADMIN_USER
        password = $ADMIN_PASSWORD
        grant_type = "password"
        client_id = "admin-cli"
    }
    
    try {
        $response = Invoke-RestMethod -Uri "$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
        Write-Host "✅ Token obtenu avec succès" -ForegroundColor Green
        return $response.access_token
    }
    catch {
        Write-Host "❌ Erreur lors de l'obtention du token: $($_.Exception.Message)" -ForegroundColor Red
        exit 1
    }
}

# Fonction pour vérifier si un realm existe
function Test-RealmExists {
    param($token, $realmName)
    
    try {
        $headers = @{ Authorization = "Bearer $token" }
        $response = Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$realmName" -Method Get -Headers $headers
        return $true
    }
    catch {
        return $false
    }
}

# Fonction pour créer le realm UnionFlow
function New-UnionFlowRealm {
    param($token)
    
    Write-Host "🏛️ Création du realm '$REALM_NAME'..." -ForegroundColor Yellow
    
    $realmConfig = @{
        realm = $REALM_NAME
        displayName = "UnionFlow"
        enabled = $true
        registrationAllowed = $true
        registrationEmailAsUsername = $true
        rememberMe = $true
        verifyEmail = $false
        loginWithEmailAllowed = $true
        duplicateEmailsAllowed = $false
        resetPasswordAllowed = $true
        editUsernameAllowed = $false
        sslRequired = "external"
        defaultLocale = "fr"
        internationalizationEnabled = $true
        supportedLocales = @("fr", "en")
    } | ConvertTo-Json -Depth 10
    
    try {
        $headers = @{ 
            Authorization = "Bearer $token"
            "Content-Type" = "application/json"
        }
        Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms" -Method Post -Body $realmConfig -Headers $headers
        Write-Host "✅ Realm '$REALM_NAME' créé avec succès" -ForegroundColor Green
        Start-Sleep -Seconds 2
    }
    catch {
        Write-Host "❌ Erreur lors de la création du realm: $($_.Exception.Message)" -ForegroundColor Red
        throw
    }
}

# Fonction pour créer le client UnionFlow Server
function New-UnionFlowClient {
    param($token)
    
    Write-Host "🔧 Création du client '$CLIENT_ID'..." -ForegroundColor Yellow
    
    $clientConfig = @{
        clientId = $CLIENT_ID
        name = "UnionFlow Server API"
        description = "Client pour l'API serveur UnionFlow"
        enabled = $true
        clientAuthenticatorType = "client-secret"
        secret = $CLIENT_SECRET
        protocol = "openid-connect"
        publicClient = $false
        serviceAccountsEnabled = $true
        authorizationServicesEnabled = $true
        standardFlowEnabled = $true
        implicitFlowEnabled = $false
        directAccessGrantsEnabled = $true
        redirectUris = @("http://localhost:8080/*", "http://localhost:3000/*")
        webOrigins = @("http://localhost:8080", "http://localhost:3000", "*")
        fullScopeAllowed = $true
        attributes = @{
            "access.token.lifespan" = "3600"
            "client.secret.creation.time" = [string][int64](Get-Date -UFormat %s)
        }
        protocolMappers = @(
            @{
                name = "email"
                protocol = "openid-connect"
                protocolMapper = "oidc-usermodel-property-mapper"
                consentRequired = $false
                config = @{
                    "userinfo.token.claim" = "true"
                    "user.attribute" = "email"
                    "id.token.claim" = "true"
                    "access.token.claim" = "true"
                    "claim.name" = "email"
                    "jsonType.label" = "String"
                }
            },
            @{
                name = "roles"
                protocol = "openid-connect"
                protocolMapper = "oidc-usermodel-realm-role-mapper"
                consentRequired = $false
                config = @{
                    "userinfo.token.claim" = "true"
                    "id.token.claim" = "true"
                    "access.token.claim" = "true"
                    "claim.name" = "roles"
                    "jsonType.label" = "String"
                    "multivalued" = "true"
                }
            }
        )
    } | ConvertTo-Json -Depth 10
    
    try {
        $headers = @{ 
            Authorization = "Bearer $token"
            "Content-Type" = "application/json"
        }
        Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/clients" -Method Post -Body $clientConfig -Headers $headers
        Write-Host "✅ Client '$CLIENT_ID' créé avec succès" -ForegroundColor Green
        Write-Host "🔑 Secret du client: $CLIENT_SECRET" -ForegroundColor Cyan
    }
    catch {
        Write-Host "❌ Erreur lors de la création du client: $($_.Exception.Message)" -ForegroundColor Red
        throw
    }
}

# Fonction pour créer les rôles
function New-UnionFlowRoles {
    param($token)
    
    Write-Host "👥 Création des rôles..." -ForegroundColor Yellow
    
    $roles = @(
        @{ name = "ADMIN"; description = "Administrateur système avec tous les droits" },
        @{ name = "PRESIDENT"; description = "Président de l'union avec droits de gestion complète" },
        @{ name = "SECRETAIRE"; description = "Secrétaire avec droits de gestion des membres et événements" },
        @{ name = "TRESORIER"; description = "Trésorier avec droits de gestion financière" },
        @{ name = "GESTIONNAIRE_MEMBRE"; description = "Gestionnaire des membres avec droits de CRUD sur les membres" },
        @{ name = "ORGANISATEUR_EVENEMENT"; description = "Organisateur d'événements avec droits de gestion des événements" },
        @{ name = "MEMBRE"; description = "Membre standard avec droits de consultation" }
    )
    
    $headers = @{ 
        Authorization = "Bearer $token"
        "Content-Type" = "application/json"
    }
    
    foreach ($role in $roles) {
        try {
            $roleJson = $role | ConvertTo-Json
            Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" -Method Post -Body $roleJson -Headers $headers
            Write-Host "  ✅ Rôle '$($role.name)' créé" -ForegroundColor Green
        }
        catch {
            Write-Host "  ⚠️ Rôle '$($role.name)' existe déjà ou erreur: $($_.Exception.Message)" -ForegroundColor Yellow
        }
    }
}

# Fonction pour créer les utilisateurs de test
function New-TestUsers {
    param($token)
    
    Write-Host "👤 Création des utilisateurs de test..." -ForegroundColor Yellow
    
    $users = @(
        @{
            username = "admin"
            email = "admin@unionflow.dev"
            firstName = "Administrateur"
            lastName = "Système"
            enabled = $true
            emailVerified = $true
            credentials = @(@{
                type = "password"
                value = "admin123"
                temporary = $false
            })
            realmRoles = @("ADMIN", "PRESIDENT")
        },
        @{
            username = "president"
            email = "president@unionflow.dev"
            firstName = "Jean"
            lastName = "Dupont"
            enabled = $true
            emailVerified = $true
            credentials = @(@{
                type = "password"
                value = "president123"
                temporary = $false
            })
            realmRoles = @("PRESIDENT", "MEMBRE")
        },
        @{
            username = "secretaire"
            email = "secretaire@unionflow.dev"
            firstName = "Marie"
            lastName = "Martin"
            enabled = $true
            emailVerified = $true
            credentials = @(@{
                type = "password"
                value = "secretaire123"
                temporary = $false
            })
            realmRoles = @("SECRETAIRE", "GESTIONNAIRE_MEMBRE", "MEMBRE")
        }
    )
    
    $headers = @{ 
        Authorization = "Bearer $token"
        "Content-Type" = "application/json"
    }
    
    foreach ($user in $users) {
        try {
            # Créer l'utilisateur
            $userJson = $user | ConvertTo-Json -Depth 10
            Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users" -Method Post -Body $userJson -Headers $headers
            Write-Host "  ✅ Utilisateur '$($user.username)' créé" -ForegroundColor Green
            
            # Attendre un peu pour que l'utilisateur soit créé
            Start-Sleep -Seconds 1
            
            # Récupérer l'ID de l'utilisateur pour assigner les rôles
            $createdUser = Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users?username=$($user.username)" -Method Get -Headers $headers
            if ($createdUser -and $createdUser.Count -gt 0) {
                $userId = $createdUser[0].id
                
                # Assigner les rôles
                foreach ($roleName in $user.realmRoles) {
                    try {
                        $role = Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles/$roleName" -Method Get -Headers $headers
                        $roleAssignment = @(@{
                            id = $role.id
                            name = $role.name
                        }) | ConvertTo-Json -Depth 10
                        
                        Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users/$userId/role-mappings/realm" -Method Post -Body $roleAssignment -Headers $headers
                        Write-Host "    ✅ Rôle '$roleName' assigné à '$($user.username)'" -ForegroundColor Green
                    }
                    catch {
                        Write-Host "    ⚠️ Erreur lors de l'assignation du rôle '$roleName': $($_.Exception.Message)" -ForegroundColor Yellow
                    }
                }
            }
        }
        catch {
            Write-Host "  ⚠️ Utilisateur '$($user.username)' existe déjà ou erreur: $($_.Exception.Message)" -ForegroundColor Yellow
        }
    }
}

# Script principal
try {
    # Obtenir le token d'administration
    $adminToken = Get-AdminToken
    
    # Vérifier si le realm existe déjà
    if (Test-RealmExists -token $adminToken -realmName $REALM_NAME) {
        Write-Host "⚠️ Le realm '$REALM_NAME' existe déjà. Suppression et recréation..." -ForegroundColor Yellow
        $headers = @{ Authorization = "Bearer $adminToken" }
        Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM_NAME" -Method Delete -Headers $headers
        Start-Sleep -Seconds 2
    }
    
    # Créer le realm
    New-UnionFlowRealm -token $adminToken
    
    # Créer le client
    New-UnionFlowClient -token $adminToken
    
    # Créer les rôles
    New-UnionFlowRoles -token $adminToken
    
    # Créer les utilisateurs de test
    New-TestUsers -token $adminToken
    
    Write-Host ""
    Write-Host "🎉 Configuration Keycloak terminée avec succès !" -ForegroundColor Green
    Write-Host "=======================================" -ForegroundColor Green
    Write-Host "📋 Informations de configuration :" -ForegroundColor Cyan
    Write-Host "   • Realm: $REALM_NAME" -ForegroundColor White
    Write-Host "   • Client ID: $CLIENT_ID" -ForegroundColor White
    Write-Host "   • Client Secret: $CLIENT_SECRET" -ForegroundColor White
    Write-Host "   • URL Auth Server: $KEYCLOAK_URL/realms/$REALM_NAME" -ForegroundColor White
    Write-Host ""
    Write-Host "👤 Utilisateurs de test créés :" -ForegroundColor Cyan
    Write-Host "   • admin / admin123 (ADMIN, PRESIDENT)" -ForegroundColor White
    Write-Host "   • president / president123 (PRESIDENT, MEMBRE)" -ForegroundColor White
    Write-Host "   • secretaire / secretaire123 (SECRETAIRE, GESTIONNAIRE_MEMBRE, MEMBRE)" -ForegroundColor White
    Write-Host ""
    Write-Host "🔧 Prochaine étape: Mettre à jour application.properties" -ForegroundColor Yellow
    
}
catch {
    Write-Host "❌ Erreur lors de la configuration: $($_.Exception.Message)" -ForegroundColor Red
    exit 1
}
