#!/usr/bin/env python3
"""
Script pour corriger le client avec les VRAIES redirect URIs du code source
"""

import requests
import json

class CorrectRedirectFixer:
    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_with_correct_redirects(self, realm_name: str = "unionflow", client_id: str = "unionflow-mobile") -> bool:
        """Corrige avec les VRAIES redirect URIs du code source"""
        print(f"🔧 Correction avec les VRAIES redirect URIs du code source...")
        
        # 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 avec les VRAIES valeurs du code source
        client_config = {
            "id": internal_id,
            "clientId": client_id,
            "name": "UnionFlow Mobile App",
            "description": "Application mobile UnionFlow avec authentification OIDC",
            "enabled": True,
            "clientAuthenticatorType": "client-secret",
            "secret": "",
            "redirectUris": [
                # VRAIES redirect URIs du code source Dart
                "dev.lions.unionflow-mobile://auth/callback",
                "dev.lions.unionflow-mobile://auth/callback/*",
                # Alternatives pour compatibilité
                "com.unionflow.mobile://login-callback",
                "com.unionflow.mobile://login-callback/*",
                # Pour les tests locaux
                "http://localhost:*",
                "http://127.0.0.1:*",
                "http://192.168.1.145:*",
                # OAuth out-of-band
                "urn:ietf:wg:oauth:2.0:oob"
            ],
            # postLogoutRedirectUris n'est pas supporté dans cette version de Keycloak
            "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",
                "pkce.code.challenge.method": "S256"
            },
            "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 mise à jour avec les VRAIES redirect URIs")
                
                # 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")
                    
                    # Afficher les redirect URIs principales
                    print(f"   ✓ Redirect URIs CORRECTES du code source:")
                    redirect_uris = config.get('redirectUris', [])
                    for uri in redirect_uris:
                        if 'dev.lions.unionflow-mobile' in uri:
                            print(f"     ✅ {uri} (CODE SOURCE)")
                        elif 'com.unionflow.mobile' in uri:
                            print(f"     ✓ {uri} (compatibilité)")
                        elif uri.startswith('http'):
                            print(f"     ✓ {uri} (tests locaux)")
                
                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 fix_complete(self):
        """Correction complète avec les vraies valeurs"""
        print("=" * 80)
        print("🔧 CORRECTION AVEC LES VRAIES REDIRECT URIs DU CODE SOURCE")
        print("=" * 80)
        print()
        print("📋 Informations trouvées dans le code source :")
        print("   • Application ID Android: dev.lions.unionflow_mobile_apps")
        print("   • Scheme de redirection: dev.lions.unionflow-mobile")
        print("   • Redirect URI principale: dev.lions.unionflow-mobile://auth/callback")
        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 self.fix_with_correct_redirects():
            print()
            print("=" * 80)
            print("🎉 CLIENT CORRIGÉ AVEC LES VRAIES REDIRECT URIs !")
            print("=" * 80)
            print()
            print("✅ REDIRECT URIs CORRECTES CONFIGURÉES :")
            print("   🎯 dev.lions.unionflow-mobile://auth/callback (PRINCIPALE)")
            print("   🎯 dev.lions.unionflow-mobile://auth/callback/*")
            print("   ✓ com.unionflow.mobile://login-callback (compatibilité)")
            print("   ✓ http://localhost:* (tests locaux)")
            print("   ✓ http://192.168.1.145:* (votre réseau)")
            print()
            print("📱 VOTRE APPLICATION MOBILE PEUT MAINTENANT :")
            print("   • S'authentifier sans erreur de redirect_uri")
            print("   • Utiliser le bon scheme: dev.lions.unionflow-mobile://")
            print("   • Recevoir les callbacks d'authentification")
            print()
            print("🚀 TESTEZ MAINTENANT VOTRE APPLICATION MOBILE !")
            print("   L'erreur 'invalid parameter: redirect_uri' est corrigée !")
            
            return True
        else:
            print()
            print("=" * 80)
            print("❌ ÉCHEC DE LA CORRECTION")
            print("=" * 80)
            return False


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


if __name__ == "__main__":
    main()
