# =============================================================================
# SCRIPT POWERSHELL D'IMPLÉMENTATION ARCHITECTURE RÔLES UNIONFLOW DANS KEYCLOAK
# =============================================================================
# 
# Ce script configure complètement l'architecture des rôles UnionFlow :
# - 8 rôles métier hiérarchiques
# - 8 comptes de test avec rôles assignés
# - Attributs utilisateur et permissions
#
# Prérequis : Keycloak accessible sur http://192.168.1.145:8180
# Realm : unionflow
# Admin : admin/admin
#
# Usage : .\Setup-UnionFlow-Keycloak.ps1
# =============================================================================

# Configuration
$KEYCLOAK_URL = "http://192.168.1.145:8180"
$REALM = "unionflow"
$ADMIN_USER = "admin"
$ADMIN_PASSWORD = "admin"
$CLIENT_ID = "unionflow-mobile"

# Fonctions d'affichage avec couleurs
function Write-Info($message) {
    Write-Host "[INFO] $message" -ForegroundColor Blue
}

function Write-Success($message) {
    Write-Host "[SUCCESS] $message" -ForegroundColor Green
}

function Write-Warning($message) {
    Write-Host "[WARNING] $message" -ForegroundColor Yellow
}

function Write-Error($message) {
    Write-Host "[ERROR] $message" -ForegroundColor Red
}

# Fonction pour obtenir le token d'administration
function Get-AdminToken {
    Write-Info "Obtention du token d'administration..."
    
    $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"
        
        if ($response.access_token) {
            $global:ADMIN_TOKEN = $response.access_token
            Write-Success "Token d'administration obtenu"
            return $true
        }
    }
    catch {
        Write-Error "Impossible d'obtenir le token d'administration: $($_.Exception.Message)"
        return $false
    }
    
    return $false
}

# Fonction pour vérifier si un rôle existe
function Test-RoleExists($roleName) {
    try {
        $headers = @{ Authorization = "Bearer $global:ADMIN_TOKEN" }
        $response = Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM/roles/$roleName" -Method Get -Headers $headers
        return $true
    }
    catch {
        return $false
    }
}

# Fonction pour créer un rôle
function New-Role($roleName, $description, $level) {
    Write-Info "Création du rôle: $roleName (niveau $level)"
    
    if (Test-RoleExists $roleName) {
        Write-Warning "Le rôle $roleName existe déjà"
        return $true
    }
    
    $roleData = @{
        name = $roleName
        description = $description
        attributes = @{
            level = @($level)
            hierarchy = @($level)
        }
    } | ConvertTo-Json -Depth 3
    
    try {
        $headers = @{ 
            Authorization = "Bearer $global:ADMIN_TOKEN"
            "Content-Type" = "application/json"
        }
        
        Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM/roles" -Method Post -Body $roleData -Headers $headers
        Write-Success "Rôle $roleName créé avec succès"
        return $true
    }
    catch {
        Write-Error "Erreur lors de la création du rôle $roleName : $($_.Exception.Message)"
        return $false
    }
}

# Fonction pour vérifier si un utilisateur existe
function Test-UserExists($username) {
    try {
        $headers = @{ Authorization = "Bearer $global:ADMIN_TOKEN" }
        $response = Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM/users?username=$username" -Method Get -Headers $headers
        return $response.Count -gt 0
    }
    catch {
        return $false
    }
}

# Fonction pour obtenir l'ID d'un utilisateur
function Get-UserId($username) {
    try {
        $headers = @{ Authorization = "Bearer $global:ADMIN_TOKEN" }
        $response = Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM/users?username=$username" -Method Get -Headers $headers
        if ($response.Count -gt 0) {
            return $response[0].id
        }
    }
    catch {
        return $null
    }
    return $null
}

# Fonction pour créer un utilisateur
function New-User($username, $email, $password, $firstName, $lastName) {
    Write-Info "Création de l'utilisateur: $username ($email)"
    
    if (Test-UserExists $username) {
        Write-Warning "L'utilisateur $username existe déjà"
        return $true
    }
    
    $userData = @{
        username = $username
        email = $email
        firstName = $firstName
        lastName = $lastName
        enabled = $true
        emailVerified = $true
        credentials = @(
            @{
                type = "password"
                value = $password
                temporary = $false
            }
        )
    } | ConvertTo-Json -Depth 3
    
    try {
        $headers = @{ 
            Authorization = "Bearer $global:ADMIN_TOKEN"
            "Content-Type" = "application/json"
        }
        
        Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM/users" -Method Post -Body $userData -Headers $headers
        Write-Success "Utilisateur $username créé avec succès"
        return $true
    }
    catch {
        Write-Error "Erreur lors de la création de l'utilisateur $username : $($_.Exception.Message)"
        return $false
    }
}

# Fonction pour assigner un rôle à un utilisateur
function Add-RoleToUser($username, $roleName) {
    Write-Info "Attribution du rôle $roleName à l'utilisateur $username"
    
    # Obtenir l'ID de l'utilisateur
    $userId = Get-UserId $username
    if (-not $userId) {
        Write-Error "Impossible de trouver l'utilisateur $username"
        return $false
    }
    
    # Obtenir les détails du rôle
    try {
        $headers = @{ Authorization = "Bearer $global:ADMIN_TOKEN" }
        $role = Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM/roles/$roleName" -Method Get -Headers $headers
        
        $assignmentData = @(
            @{
                id = $role.id
                name = $role.name
            }
        ) | ConvertTo-Json -Depth 2
        
        $headers["Content-Type"] = "application/json"
        Invoke-RestMethod -Uri "$KEYCLOAK_URL/admin/realms/$REALM/users/$userId/role-mappings/realm" -Method Post -Body $assignmentData -Headers $headers
        
        Write-Success "Rôle $roleName assigné à $username"
        return $true
    }
    catch {
        Write-Error "Erreur lors de l'assignation du rôle $roleName à $username : $($_.Exception.Message)"
        return $false
    }
}

# =============================================================================
# DÉBUT DU SCRIPT PRINCIPAL
# =============================================================================

Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host "🚀 CONFIGURATION ARCHITECTURE RÔLES UNIONFLOW DANS KEYCLOAK" -ForegroundColor Cyan
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host ""

# Étape 1: Obtenir le token d'administration
if (-not (Get-AdminToken)) {
    Write-Error "Impossible de continuer sans token d'administration"
    exit 1
}

Write-Host ""
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host "📋 ÉTAPE 1: CRÉATION DES RÔLES MÉTIER" -ForegroundColor Cyan
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host ""

# Création des 8 rôles métier avec hiérarchie
$roles = @(
    @{ Name = "SUPER_ADMINISTRATEUR"; Description = "Super Administrateur - Accès système complet"; Level = "100" },
    @{ Name = "ADMINISTRATEUR_ORGANISATION"; Description = "Administrateur Organisation - Gestion complète organisation"; Level = "85" },
    @{ Name = "RESPONSABLE_TECHNIQUE"; Description = "Responsable Technique - Configuration et workflows"; Level = "80" },
    @{ Name = "RESPONSABLE_FINANCIER"; Description = "Responsable Financier - Gestion finances et budget"; Level = "75" },
    @{ Name = "RESPONSABLE_MEMBRES"; Description = "Responsable Membres - Gestion communauté"; Level = "70" },
    @{ Name = "MEMBRE_ACTIF"; Description = "Membre Actif - Participation et organisation"; Level = "50" },
    @{ Name = "MEMBRE_SIMPLE"; Description = "Membre Simple - Participation standard"; Level = "30" },
    @{ Name = "VISITEUR"; Description = "Visiteur - Accès public découverte"; Level = "0" }
)

foreach ($role in $roles) {
    New-Role $role.Name $role.Description $role.Level
}

Write-Host ""
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host "👥 ÉTAPE 2: CRÉATION DES COMPTES DE TEST" -ForegroundColor Cyan
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host ""

# Création des 8 comptes de test
$users = @(
    @{ Username = "superadmin"; Email = "superadmin@unionflow.dev"; Password = "SuperAdmin123!"; FirstName = "Super"; LastName = "Admin" },
    @{ Username = "admin.org"; Email = "admin@association-dev.fr"; Password = "AdminOrg123!"; FirstName = "Admin"; LastName = "Organisation" },
    @{ Username = "tech.lead"; Email = "tech@association-dev.fr"; Password = "TechLead123!"; FirstName = "Tech"; LastName = "Lead" },
    @{ Username = "tresorier"; Email = "tresorier@association-dev.fr"; Password = "Tresorier123!"; FirstName = "Trésorier"; LastName = "Finance" },
    @{ Username = "rh.manager"; Email = "rh@association-dev.fr"; Password = "RhManager123!"; FirstName = "RH"; LastName = "Manager" },
    @{ Username = "marie.active"; Email = "marie@association-dev.fr"; Password = "Marie123!"; FirstName = "Marie"; LastName = "Active" },
    @{ Username = "jean.simple"; Email = "jean@association-dev.fr"; Password = "Jean123!"; FirstName = "Jean"; LastName = "Simple" },
    @{ Username = "visiteur"; Email = "visiteur@example.com"; Password = "Visiteur123!"; FirstName = "Visiteur"; LastName = "Public" }
)

foreach ($user in $users) {
    New-User $user.Username $user.Email $user.Password $user.FirstName $user.LastName
}

Write-Host ""
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host "🔗 ÉTAPE 3: ATTRIBUTION DES RÔLES AUX UTILISATEURS" -ForegroundColor Cyan
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host ""

# Attribution des rôles aux utilisateurs
$userRoleAssignments = @(
    @{ Username = "superadmin"; Role = "SUPER_ADMINISTRATEUR" },
    @{ Username = "admin.org"; Role = "ADMINISTRATEUR_ORGANISATION" },
    @{ Username = "tech.lead"; Role = "RESPONSABLE_TECHNIQUE" },
    @{ Username = "tresorier"; Role = "RESPONSABLE_FINANCIER" },
    @{ Username = "rh.manager"; Role = "RESPONSABLE_MEMBRES" },
    @{ Username = "marie.active"; Role = "MEMBRE_ACTIF" },
    @{ Username = "jean.simple"; Role = "MEMBRE_SIMPLE" },
    @{ Username = "visiteur"; Role = "VISITEUR" }
)

foreach ($assignment in $userRoleAssignments) {
    Add-RoleToUser $assignment.Username $assignment.Role
}

Write-Host ""
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host "✅ CONFIGURATION TERMINÉE AVEC SUCCÈS" -ForegroundColor Cyan
Write-Host "=============================================================================" -ForegroundColor Cyan
Write-Host ""

Write-Success "Architecture des rôles UnionFlow configurée dans Keycloak !"
Write-Host ""
Write-Host "📋 RÉSUMÉ DE LA CONFIGURATION :" -ForegroundColor White
Write-Host "• 8 rôles métier créés avec hiérarchie" -ForegroundColor White
Write-Host "• 8 comptes de test créés et configurés" -ForegroundColor White
Write-Host "• Rôles assignés aux utilisateurs appropriés" -ForegroundColor White
Write-Host ""
Write-Host "🔐 COMPTES DE TEST DISPONIBLES :" -ForegroundColor White
Write-Host "• superadmin@unionflow.dev (SUPER_ADMINISTRATEUR)" -ForegroundColor White
Write-Host "• admin@association-dev.fr (ADMINISTRATEUR_ORGANISATION)" -ForegroundColor White
Write-Host "• tech@association-dev.fr (RESPONSABLE_TECHNIQUE)" -ForegroundColor White
Write-Host "• tresorier@association-dev.fr (RESPONSABLE_FINANCIER)" -ForegroundColor White
Write-Host "• rh@association-dev.fr (RESPONSABLE_MEMBRES)" -ForegroundColor White
Write-Host "• marie@association-dev.fr (MEMBRE_ACTIF)" -ForegroundColor White
Write-Host "• jean@association-dev.fr (MEMBRE_SIMPLE)" -ForegroundColor White
Write-Host "• visiteur@example.com (VISITEUR)" -ForegroundColor White
Write-Host ""
Write-Host "🚀 Vous pouvez maintenant tester l'authentification avec ces comptes !" -ForegroundColor Green
