#!/usr/bin/env pwsh
<#
.SYNOPSIS
    Script pour configurer Keycloak en production pour Lions User Manager

.DESCRIPTION
    Ce script configure Keycloak production avec :
    - Création des clients OIDC (frontend + backend)
    - Création des rôles realm
    - Configuration des protocol mappers
    - Assignation des rôles au service account

.PARAMETER KeycloakUrl
    URL de Keycloak (défaut: https://security.lions.dev)

.PARAMETER Realm
    Realm Keycloak (défaut: master)

.PARAMETER AdminUsername
    Nom d'utilisateur admin Keycloak

.PARAMETER AdminPassword
    Mot de passe admin Keycloak

.EXAMPLE
    .\setup-keycloak-production.ps1 -AdminUsername admin -AdminPassword "your-password"
#>

param(
    [Parameter(Mandatory=$false)]
    [string]$KeycloakUrl = "https://security.lions.dev",
    
    [Parameter(Mandatory=$false)]
    [string]$Realm = "master",
    
    [Parameter(Mandatory=$true)]
    [string]$AdminUsername,
    
    [Parameter(Mandatory=$true)]
    [string]$AdminPassword
)

$ErrorActionPreference = "Stop"

# Couleurs
function Write-Success { Write-Host "✅ $args" -ForegroundColor Green }
function Write-Info { Write-Host "ℹ️  $args" -ForegroundColor Cyan }
function Write-Warning { Write-Host "⚠️  $args" -ForegroundColor Yellow }
function Write-Error { Write-Host "❌ $args" -ForegroundColor Red }
function Write-Step { Write-Host "`n🚀 $args" -ForegroundColor Magenta }

Write-Host @"

╔═══════════════════════════════════════════════════════════════════════════════╗
║                                                                               ║
║        🔐 CONFIGURATION KEYCLOAK PRODUCTION - LIONS USER MANAGER 🔐          ║
║                                                                               ║
╚═══════════════════════════════════════════════════════════════════════════════╝

"@ -ForegroundColor Cyan

Write-Info "Keycloak URL: $KeycloakUrl"
Write-Info "Realm: $Realm"
Write-Info "Admin Username: $AdminUsername"
Write-Info ""

# 1. Obtenir le token admin
Write-Step "1. Obtention du token admin Keycloak..."

$tokenUrl = "$KeycloakUrl/realms/$Realm/protocol/openid-connect/token"
$tokenBody = @{
    username = $AdminUsername
    password = $AdminPassword
    grant_type = "password"
    client_id = "admin-cli"
} | ConvertTo-Json

try {
    $tokenResponse = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body $tokenBody -ContentType "application/json"
    $accessToken = $tokenResponse.access_token
    
    if ([string]::IsNullOrEmpty($accessToken)) {
        Write-Error "Impossible d'obtenir le token admin"
        exit 1
    }
    
    Write-Success "Token admin obtenu"
} catch {
    Write-Error "Erreur lors de l'obtention du token: $($_.Exception.Message)"
    exit 1
}

$headers = @{
    "Authorization" = "Bearer $accessToken"
    "Content-Type" = "application/json"
}

# 2. Créer les rôles realm
Write-Step "2. Création des rôles realm..."

$roles = @(
    @{name="admin"; description="System administrator with full access"},
    @{name="user_manager"; description="User manager - Can create, update, delete users"},
    @{name="user_viewer"; description="User viewer - Read-only access to users"},
    @{name="auditor"; description="Auditor - Can view audit logs"},
    @{name="sync_manager"; description="Sync manager - Can manage synchronization"},
    @{name="role_manager"; description="Role manager - Can create, update, delete roles"},
    @{name="role_viewer"; description="Role viewer - Read-only access to roles"}
)

foreach ($role in $roles) {
    $roleUrl = "$KeycloakUrl/admin/realms/$Realm/roles"
    $roleBody = @{
        name = $role.name
        description = $role.description
        composite = $false
        clientRole = $false
    } | ConvertTo-Json -Compress
    
    try {
        $existingRole = Invoke-RestMethod -Uri "$roleUrl/$($role.name)" -Method Get -Headers $headers -ErrorAction SilentlyContinue
        Write-Warning "Rôle $($role.name) existe déjà, ignoré"
    } catch {
        try {
            Invoke-RestMethod -Uri $roleUrl -Method Post -Headers $headers -Body $roleBody | Out-Null
            Write-Success "Rôle $($role.name) créé"
        } catch {
            Write-Warning "Erreur création rôle $($role.name): $($_.Exception.Message)"
        }
    }
}

# 3. Créer le client frontend
Write-Step "3. Création du client frontend (lions-user-manager-client)..."

$frontendClientUrl = "$KeycloakUrl/admin/realms/$Realm/clients"
$frontendClientBody = @{
    clientId = "lions-user-manager-client"
    name = "Lions User Manager Client (Frontend)"
    description = "Frontend application for Lions User Manager"
    enabled = $true
    publicClient = $true
    standardFlowEnabled = $true
    directAccessGrantsEnabled = $false
    serviceAccountsEnabled = $false
    redirectUris = @(
        "https://user-manager.lions.dev/*",
        "https://admin.lions.dev/*",
        "https://user-manager.lions.dev/auth/callback"
    )
    webOrigins = @(
        "https://user-manager.lions.dev",
        "https://admin.lions.dev"
    )
    protocol = "openid-connect"
    attributes = @{
        "pkce.code.challenge.method" = "S256"
        "use.refresh.tokens" = "true"
        "frontchannel.logout.session.required" = "true"
    }
} | ConvertTo-Json -Depth 10 -Compress

try {
    # Vérifier si le client existe
    $clients = Invoke-RestMethod -Uri $frontendClientUrl -Method Get -Headers $headers
    $existingClient = $clients | Where-Object { $_.clientId -eq "lions-user-manager-client" }
    
    if ($existingClient) {
        Write-Warning "Client frontend existe déjà (ID: $($existingClient.id))"
        $frontendClientId = $existingClient.id
    } else {
        $response = Invoke-RestMethod -Uri $frontendClientUrl -Method Post -Headers $headers -Body $frontendClientBody
        Write-Success "Client frontend créé"
        
        # Récupérer l'ID du client créé
        $clients = Invoke-RestMethod -Uri $frontendClientUrl -Method Get -Headers $headers
        $frontendClient = $clients | Where-Object { $_.clientId -eq "lions-user-manager-client" }
        $frontendClientId = $frontendClient.id
    }
} catch {
    Write-Error "Erreur création client frontend: $($_.Exception.Message)"
    exit 1
}

# 4. Créer le client backend (service account)
Write-Step "4. Création du client backend (lions-user-manager) avec service account..."

$backendClientUrl = "$KeycloakUrl/admin/realms/$Realm/clients"
$backendClientBody = @{
    clientId = "lions-user-manager"
    name = "Lions User Manager Server (Backend)"
    description = "Backend API for Lions User Manager with service account"
    enabled = $true
    publicClient = $false
    standardFlowEnabled = $false
    directAccessGrantsEnabled = $true
    serviceAccountsEnabled = $true
    authorizationServicesEnabled = $true
    protocol = "openid-connect"
    attributes = @{
        "access.token.lifespan" = "300"
        "client.session.idle.timeout" = "1800"
        "client.session.max.lifespan" = "36000"
    }
} | ConvertTo-Json -Depth 10 -Compress

try {
    # Vérifier si le client existe
    $clients = Invoke-RestMethod -Uri $backendClientUrl -Method Get -Headers $headers
    $existingClient = $clients | Where-Object { $_.clientId -eq "lions-user-manager" }
    
    if ($existingClient) {
        Write-Warning "Client backend existe déjà (ID: $($existingClient.id))"
        $backendClientId = $existingClient.id
    } else {
        $response = Invoke-RestMethod -Uri $backendClientUrl -Method Post -Headers $headers -Body $backendClientBody
        Write-Success "Client backend créé"
        
        # Récupérer l'ID du client créé
        $clients = Invoke-RestMethod -Uri $backendClientUrl -Method Get -Headers $headers
        $backendClient = $clients | Where-Object { $_.clientId -eq "lions-user-manager" }
        $backendClientId = $backendClient.id
    }
    
    # Récupérer le secret du client backend
    $secretUrl = "$KeycloakUrl/admin/realms/$Realm/clients/$backendClientId/client-secret"
    $secretResponse = Invoke-RestMethod -Uri $secretUrl -Method Get -Headers $headers
    $backendSecret = $secretResponse.value
    
    Write-Success "Secret backend récupéré: $backendSecret"
    Write-Info "⚠️  IMPORTANT: Sauvegardez ce secret pour la configuration Kubernetes !"
    
} catch {
    Write-Error "Erreur création client backend: $($_.Exception.Message)"
    exit 1
}

# 5. Assigner les rôles au service account
Write-Step "5. Assignation des rôles au service account backend..."

try {
    # Récupérer l'ID du service account
    $serviceAccountUrl = "$KeycloakUrl/admin/realms/$Realm/clients/$backendClientId/service-account-user"
    $serviceAccount = Invoke-RestMethod -Uri $serviceAccountUrl -Method Get -Headers $headers
    $serviceAccountId = $serviceAccount.id
    
    # Récupérer les rôles à assigner
    $rolesToAssign = @("admin", "user_manager", "auditor", "sync_manager", "role_manager")
    $realmRoles = Invoke-RestMethod -Uri "$KeycloakUrl/admin/realms/$Realm/roles" -Method Get -Headers $headers
    $rolesToAssignObjects = $realmRoles | Where-Object { $rolesToAssign -contains $_.name }
    
    # Assigner les rôles
    $assignRolesUrl = "$KeycloakUrl/admin/realms/$Realm/users/$serviceAccountId/role-mappings/realm"
    $rolesBody = $rolesToAssignObjects | ConvertTo-Json -Depth 10
    
    Invoke-RestMethod -Uri $assignRolesUrl -Method Post -Headers $headers -Body $rolesBody | Out-Null
    Write-Success "Rôles assignés au service account: $($rolesToAssign -join ', ')"
    
} catch {
    Write-Warning "Erreur assignation rôles au service account: $($_.Exception.Message)"
    Write-Info "Vous devrez assigner les rôles manuellement dans Keycloak Admin Console"
}

# 6. Vérifier le protocol mapper roles
Write-Step "6. Vérification du protocol mapper 'roles'..."

try {
    $clientScopesUrl = "$KeycloakUrl/admin/realms/$Realm/client-scopes"
    $clientScopes = Invoke-RestMethod -Uri $clientScopesUrl -Method Get -Headers $headers
    $rolesScope = $clientScopes | Where-Object { $_.name -eq "roles" }
    
    if ($rolesScope) {
        $mappersUrl = "$KeycloakUrl/admin/realms/$Realm/client-scopes/$($rolesScope.id)/protocol-mappers/models"
        $mappers = Invoke-RestMethod -Uri $mappersUrl -Method Get -Headers $headers
        $realmRolesMapper = $mappers | Where-Object { $_.name -eq "realm roles" }
        
        if ($realmRolesMapper) {
            Write-Success "Protocol mapper 'realm roles' trouvé"
            Write-Info "Vérifiez qu'il est configuré pour l'access token (claim: realm_access.roles)"
        } else {
            Write-Warning "Protocol mapper 'realm roles' non trouvé - à créer manuellement"
        }
    } else {
        Write-Warning "Client scope 'roles' non trouvé - à créer manuellement"
    }
} catch {
    Write-Warning "Erreur vérification protocol mapper: $($_.Exception.Message)"
}

# 7. Résumé
Write-Step "7. Résumé de la configuration..."

Write-Host @"

╔═══════════════════════════════════════════════════════════════════════════════╗
║                                                                               ║
║                    ✅ CONFIGURATION KEYCLOAK TERMINÉE ✅                      ║
║                                                                               ║
╚═══════════════════════════════════════════════════════════════════════════════╝

"@ -ForegroundColor Green

Write-Host "📋 INFORMATIONS IMPORTANTES:" -ForegroundColor Yellow
Write-Host ""
Write-Host "🔑 SECRET BACKEND (Service Account):" -ForegroundColor Cyan
Write-Host "   $backendSecret" -ForegroundColor White
Write-Host ""
Write-Host "⚠️  ACTIONS REQUISES:" -ForegroundColor Yellow
Write-Host "   1. Sauvegardez le secret backend ci-dessus"
Write-Host "   2. Vérifiez le protocol mapper 'roles' dans Keycloak Admin Console"
Write-Host "   3. Vérifiez que les rôles sont assignés au service account"
Write-Host "   4. Créez les secrets Kubernetes avec ces informations"
Write-Host ""
Write-Host "🔗 URLS:" -ForegroundColor Cyan
Write-Host "   Keycloak Admin: $KeycloakUrl/admin"
Write-Host "   Realm: $Realm"
Write-Host ""

