#!/usr/bin/env python3
"""
Script pour corriger la configuration du client unionflow-mobile
Spécifiquement les redirect_uri pour l'application mobile
"""

import requests
import json

class ClientRedirectFixer:
    def __init__(self, base_url: str = "http://localhost:8180"):
        self.base_url = base_url
        self.session = requests.Session()
        self.admin_token = None
        
    def get_admin_token(self) -> bool:
        """Obtient le token admin"""
        try:
            data = {
                "username": "admin",
                "password": "admin",
                "grant_type": "password",
                "client_id": "admin-cli"
            }
            
            response = self.session.post(
                f"{self.base_url}/realms/master/protocol/openid-connect/token",
                data=data,
                headers={"Content-Type": "application/x-www-form-urlencoded"}
            )
            
            if response.status_code == 200:
                token_data = response.json()
                self.admin_token = token_data.get("access_token")
                return self.admin_token is not None
                
        except Exception as e:
            print(f"Erreur obtention token: {e}")
            
        return False
    
    def get_client_internal_id(self, realm_name: str, client_id: str) -> str:
        """Obtient l'ID interne du client"""
        try:
            response = self.session.get(
                f"{self.base_url}/admin/realms/{realm_name}/clients",
                headers={"Authorization": f"Bearer {self.admin_token}"}
            )
            
            if response.status_code == 200:
                clients = response.json()
                for client in clients:
                    if client.get("clientId") == client_id:
                        return client.get("id")
            
        except Exception as e:
            print(f"Erreur récupération client ID: {e}")
            
        return None
    
    def fix_client_configuration(self, realm_name: str = "unionflow", client_id: str = "unionflow-mobile") -> bool:
        """Corrige la configuration du client pour mobile"""
        print(f"🔧 Correction de la configuration du client {client_id}...")
        
        # 1. Obtenir l'ID interne du client
        internal_id = self.get_client_internal_id(realm_name, client_id)
        if not internal_id:
            print(f"   ❌ Client {client_id} non trouvé")
            return False
        
        print(f"   ✓ Client trouvé (ID interne: {internal_id})")
        
        # 2. Configuration correcte pour une application mobile
        client_config = {
            "id": internal_id,
            "clientId": client_id,
            "name": "UnionFlow Mobile App",
            "description": "Client pour l'application mobile UnionFlow",
            "enabled": True,
            "clientAuthenticatorType": "client-secret",
            "secret": "",
            "redirectUris": [
                "http://localhost:*",
                "http://127.0.0.1:*",
                "http://192.168.1.145:*",
                "unionflow://oauth/callback",
                "unionflow://login",
                "com.unionflow.mobile://oauth",
                "urn:ietf:wg:oauth:2.0:oob"
            ],
            "webOrigins": [
                "http://localhost",
                "http://127.0.0.1",
                "http://192.168.1.145",
                "+"
            ],
            "notBefore": 0,
            "bearerOnly": False,
            "consentRequired": False,
            "standardFlowEnabled": True,
            "implicitFlowEnabled": False,
            "directAccessGrantsEnabled": True,
            "serviceAccountsEnabled": False,
            "publicClient": True,
            "frontchannelLogout": False,
            "protocol": "openid-connect",
            "attributes": {
                "saml.assertion.signature": "false",
                "saml.force.post.binding": "false",
                "saml.multivalued.roles": "false",
                "saml.encrypt": "false",
                "saml.server.signature": "false",
                "saml.server.signature.keyinfo.ext": "false",
                "exclude.session.state.from.auth.response": "false",
                "saml_force_name_id_format": "false",
                "saml.client.signature": "false",
                "tls.client.certificate.bound.access.tokens": "false",
                "saml.authnstatement": "false",
                "display.on.consent.screen": "false",
                "saml.onetimeuse.condition": "false",
                "access.token.lifespan": "300",
                "client_credentials.use_refresh_token": "false",
                "oauth2.device.authorization.grant.enabled": "false",
                "oidc.ciba.grant.enabled": "false"
            },
            "authenticationFlowBindingOverrides": {},
            "fullScopeAllowed": True,
            "nodeReRegistrationTimeout": -1,
            "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"],
            "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"]
        }
        
        try:
            # 3. Mettre à jour la configuration
            response = self.session.put(
                f"{self.base_url}/admin/realms/{realm_name}/clients/{internal_id}",
                json=client_config,
                headers={
                    "Authorization": f"Bearer {self.admin_token}",
                    "Content-Type": "application/json"
                }
            )
            
            if response.status_code == 204:
                print(f"   ✅ Configuration du client mise à jour")
                
                # 4. Vérifier la configuration
                verify_response = self.session.get(
                    f"{self.base_url}/admin/realms/{realm_name}/clients/{internal_id}",
                    headers={"Authorization": f"Bearer {self.admin_token}"}
                )
                
                if verify_response.status_code == 200:
                    config = verify_response.json()
                    print(f"   ✓ Configuration vérifiée:")
                    print(f"     - Public Client: {config.get('publicClient')}")
                    print(f"     - Direct Access Grants: {config.get('directAccessGrantsEnabled')}")
                    print(f"     - Standard Flow: {config.get('standardFlowEnabled')}")
                    print(f"     - Redirect URIs: {len(config.get('redirectUris', []))} configurées")
                    print(f"     - Web Origins: {len(config.get('webOrigins', []))} configurées")
                    
                    # Afficher les redirect URIs
                    print(f"   ✓ Redirect URIs configurées:")
                    for uri in config.get('redirectUris', []):
                        print(f"     - {uri}")
                
                return True
            else:
                print(f"   ❌ Erreur mise à jour: {response.status_code}")
                print(f"       Réponse: {response.text}")
                return False
                
        except Exception as e:
            print(f"   ❌ Exception: {e}")
            return False
    
    def test_client_after_fix(self, realm_name: str = "unionflow", client_id: str = "unionflow-mobile") -> bool:
        """Teste le client après correction"""
        print(f"🧪 Test du client après correction...")
        
        # Test d'authentification simple (Resource Owner Password Credentials)
        test_data = {
            "username": "marie.active",
            "password": "Marie123!",
            "grant_type": "password",
            "client_id": client_id
        }
        
        try:
            response = self.session.post(
                f"{self.base_url}/realms/{realm_name}/protocol/openid-connect/token",
                data=test_data,
                headers={"Content-Type": "application/x-www-form-urlencoded"}
            )
            
            print(f"   Status: {response.status_code}")
            
            if response.status_code == 200:
                token_data = response.json()
                if "access_token" in token_data:
                    print(f"   ✅ AUTHENTIFICATION RÉUSSIE !")
                    print(f"   ✓ Token reçu")
                    return True
                else:
                    print(f"   ❌ Token manquant")
            else:
                print(f"   ❌ Authentification échouée")
                print(f"       Réponse: {response.text}")
            
        except Exception as e:
            print(f"   ❌ Exception: {e}")
        
        return False
    
    def fix_complete(self):
        """Correction complète du client"""
        print("=" * 80)
        print("🔧 CORRECTION DU CLIENT UNIONFLOW-MOBILE")
        print("=" * 80)
        print()
        
        if not self.get_admin_token():
            print("❌ Impossible d'obtenir le token admin")
            return False
        
        print("✅ Token admin obtenu")
        print()
        
        # Corriger la configuration
        if not self.fix_client_configuration():
            print("❌ Échec de la correction du client")
            return False
        
        print()
        
        # Tester le client
        if self.test_client_after_fix():
            print()
            print("=" * 80)
            print("🎉 CLIENT CORRIGÉ AVEC SUCCÈS !")
            print("=" * 80)
            print()
            print("🚀 Le client unionflow-mobile est maintenant correctement configuré")
            print("   pour votre application mobile avec les redirect URIs appropriées.")
            print()
            print("📱 REDIRECT URIs CONFIGURÉES :")
            print("   • http://localhost:* (pour tests locaux)")
            print("   • http://127.0.0.1:* (pour tests locaux)")
            print("   • http://192.168.1.145:* (pour votre réseau)")
            print("   • unionflow://oauth/callback (pour l'app mobile)")
            print("   • unionflow://login (pour l'app mobile)")
            print("   • com.unionflow.mobile://oauth (pour l'app mobile)")
            print("   • urn:ietf:wg:oauth:2.0:oob (pour OAuth out-of-band)")
            print()
            print("✅ Votre application mobile peut maintenant s'authentifier !")
            return True
        else:
            print()
            print("=" * 80)
            print("⚠️ CLIENT CORRIGÉ MAIS PROBLÈME D'AUTHENTIFICATION")
            print("=" * 80)
            print()
            print("Le client a été reconfiguré mais l'authentification échoue encore.")
            print("Cela peut être dû aux utilisateurs. Essayez la configuration manuelle :")
            print()
            print("1. Ouvrez http://localhost:8180/admin/")
            print("2. Connectez-vous avec admin/admin")
            print("3. Realm 'unionflow' > Users > marie.active")
            print("4. Credentials > Set password > Marie123! (non temporaire)")
            return False


def main():
    fixer = ClientRedirectFixer()
    fixer.fix_complete()


if __name__ == "__main__":
    main()
