package dev.lions.user.manager.config;

import io.quarkus.runtime.StartupEvent;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;

import java.util.*;

/**
 * Configuration automatique de Keycloak pour l'utilisateur de test
 * S'exécute au démarrage de l'application en mode dev
 */
@Singleton
@Slf4j
public class KeycloakTestUserConfig {

    @Inject
    @ConfigProperty(name = "quarkus.profile", defaultValue = "prod")
    String profile;

    @Inject
    @ConfigProperty(name = "lions.keycloak.server-url")
    String keycloakServerUrl;

    @Inject
    @ConfigProperty(name = "lions.keycloak.admin-realm", defaultValue = "master")
    String adminRealm;

    @Inject
    @ConfigProperty(name = "lions.keycloak.admin-username", defaultValue = "admin")
    String adminUsername;

    @Inject
    @ConfigProperty(name = "lions.keycloak.admin-password", defaultValue = "admin")
    String adminPassword;

    @Inject
    @ConfigProperty(name = "lions.keycloak.authorized-realms")
    String authorizedRealms;

    private static final String TEST_REALM = "lions-user-manager";
    private static final String TEST_USER = "test-user";
    private static final String TEST_PASSWORD = "test123";
    private static final String TEST_EMAIL = "test@lions.dev";
    private static final String CLIENT_ID = "lions-user-manager-client";

    private static final List<String> REQUIRED_ROLES = Arrays.asList(
        "admin", "user_manager", "user_viewer", 
        "role_manager", "role_viewer", "auditor", "sync_manager"
    );

    void onStart(@Observes StartupEvent ev) {
        // DÉSACTIVÉ: Configuration manuelle via script create-roles-and-assign.sh
        // Cette configuration automatique cause des erreurs de compatibilité Keycloak
        // (bruteForceStrategy, cpuInfo non reconnus par la version Keycloak client)
        log.info("Configuration automatique de Keycloak DÉSACTIVÉE");
        log.info("Utiliser le script create-roles-and-assign.sh pour configurer Keycloak manuellement");
        return;

        /* ANCIEN CODE DÉSACTIVÉ
        // Ne s'exécuter qu'en mode dev
        if (!"dev".equals(profile) && !"development".equals(profile)) {
            log.debug("Mode non-dev détecté ({}), configuration Keycloak ignorée", profile);
            return;
        }

        log.info("Configuration automatique de Keycloak pour l'utilisateur de test...");

        Keycloak adminClient = null;
        try {
            // Connexion en tant qu'admin
            adminClient = KeycloakBuilder.builder()
                .serverUrl(keycloakServerUrl)
                .realm(adminRealm)
                .username(adminUsername)
                .password(adminPassword)
                .clientId("admin-cli")
                .build();

            // 1. Vérifier/Créer le realm
            ensureRealmExists(adminClient);

            // 2. Créer les rôles
            ensureRolesExist(adminClient);

            // 3. Créer l'utilisateur de test
            String userId = ensureTestUserExists(adminClient);

            // 4. Assigner les rôles
            assignRolesToUser(adminClient, userId);

            // 5. Vérifier/Créer le client et le mapper
            ensureClientAndMapper(adminClient);

            log.info("✓ Configuration Keycloak terminée avec succès");
            log.info("  Utilisateur de test: {} / {}", TEST_USER, TEST_PASSWORD);
            log.info("  Rôles assignés: {}", String.join(", ", REQUIRED_ROLES));

        } catch (Exception e) {
            log.error("Erreur lors de la configuration Keycloak: {}", e.getMessage(), e);
        } finally {
            if (adminClient != null) {
                adminClient.close();
            }
        }
        */
    }

    private void ensureRealmExists(Keycloak adminClient) {
        try {
            adminClient.realms().realm(TEST_REALM).toRepresentation();
            log.debug("Realm '{}' existe déjà", TEST_REALM);
        } catch (jakarta.ws.rs.NotFoundException e) {
            log.info("Création du realm '{}'...", TEST_REALM);
            RealmRepresentation realm = new RealmRepresentation();
            realm.setRealm(TEST_REALM);
            realm.setEnabled(true);
            adminClient.realms().create(realm);
            log.info("✓ Realm '{}' créé", TEST_REALM);
        }
    }

    private void ensureRolesExist(Keycloak adminClient) {
        var rolesResource = adminClient.realms().realm(TEST_REALM).roles();
        
        for (String roleName : REQUIRED_ROLES) {
            try {
                rolesResource.get(roleName).toRepresentation();
                log.debug("Rôle '{}' existe déjà", roleName);
            } catch (jakarta.ws.rs.NotFoundException e) {
                log.info("Création du rôle '{}'...", roleName);
                RoleRepresentation role = new RoleRepresentation();
                role.setName(roleName);
                role.setDescription("Rôle " + roleName + " pour lions-user-manager");
                rolesResource.create(role);
                log.info("✓ Rôle '{}' créé", roleName);
            }
        }
    }

    private String ensureTestUserExists(Keycloak adminClient) {
        var usersResource = adminClient.realms().realm(TEST_REALM).users();
        
        // Chercher l'utilisateur
        List<UserRepresentation> users = usersResource.search(TEST_USER, true);
        
        String userId;
        if (users != null && !users.isEmpty()) {
            userId = users.get(0).getId();
            log.debug("Utilisateur '{}' existe déjà (ID: {})", TEST_USER, userId);
        } else {
            log.info("Création de l'utilisateur '{}'...", TEST_USER);
            UserRepresentation user = new UserRepresentation();
            user.setUsername(TEST_USER);
            user.setEmail(TEST_EMAIL);
            user.setFirstName("Test");
            user.setLastName("User");
            user.setEnabled(true);
            user.setEmailVerified(true);
            
            jakarta.ws.rs.core.Response response = usersResource.create(user);
            userId = getCreatedId(response);
            
            // Définir le mot de passe
            CredentialRepresentation credential = new CredentialRepresentation();
            credential.setType(CredentialRepresentation.PASSWORD);
            credential.setValue(TEST_PASSWORD);
            credential.setTemporary(false);
            usersResource.get(userId).resetPassword(credential);
            
            log.info("✓ Utilisateur '{}' créé (ID: {})", TEST_USER, userId);
        }
        
        return userId;
    }

    private void assignRolesToUser(Keycloak adminClient, String userId) {
        var usersResource = adminClient.realms().realm(TEST_REALM).users();
        var rolesResource = adminClient.realms().realm(TEST_REALM).roles();
        
        List<RoleRepresentation> rolesToAssign = new ArrayList<>();
        for (String roleName : REQUIRED_ROLES) {
            RoleRepresentation role = rolesResource.get(roleName).toRepresentation();
            rolesToAssign.add(role);
        }
        
        usersResource.get(userId).roles().realmLevel().add(rolesToAssign);
        log.info("✓ {} rôles assignés à l'utilisateur", rolesToAssign.size());
    }

    private void ensureClientAndMapper(Keycloak adminClient) {
        try {
            var clientsResource = adminClient.realms().realm(TEST_REALM).clients();
            var clients = clientsResource.findByClientId(CLIENT_ID);
            
            String clientId;
            if (clients == null || clients.isEmpty()) {
                log.info("Création du client '{}'...", CLIENT_ID);
                org.keycloak.representations.idm.ClientRepresentation client = new org.keycloak.representations.idm.ClientRepresentation();
                client.setClientId(CLIENT_ID);
                client.setName(CLIENT_ID);
                client.setDescription("Client OIDC pour lions-user-manager");
                client.setEnabled(true);
                client.setPublicClient(false);
                client.setStandardFlowEnabled(true);
                client.setDirectAccessGrantsEnabled(true);
                client.setFullScopeAllowed(true); // IMPORTANT: Permet d'inclure tous les rôles dans le token
                client.setRedirectUris(java.util.Arrays.asList(
                    "http://localhost:8080/*",
                    "http://localhost:8080/auth/callback"
                ));
                client.setWebOrigins(java.util.Arrays.asList("http://localhost:8080"));
                client.setSecret("NTuaQpk5E6qiMqAWTFrCOcIkOABzZzKO");
                
                jakarta.ws.rs.core.Response response = clientsResource.create(client);
                clientId = getCreatedId(response);
                log.info("✓ Client '{}' créé (ID: {})", CLIENT_ID, clientId);
            } else {
                clientId = clients.get(0).getId();
                log.debug("Client '{}' existe déjà (ID: {})", CLIENT_ID, clientId);
            }
            
            // Ajouter le scope "roles" par défaut au client
            try {
                var clientScopesResource = adminClient.realms().realm(TEST_REALM).clientScopes();
                var defaultClientScopes = clientScopesResource.findAll();
                var rolesScope = defaultClientScopes.stream()
                    .filter(s -> "roles".equals(s.getName()))
                    .findFirst();
                
                if (rolesScope.isPresent()) {
                    var clientResource = clientsResource.get(clientId);
                    var defaultScopes = clientResource.getDefaultClientScopes();
                    boolean hasRolesScope = defaultScopes.stream()
                        .anyMatch(s -> "roles".equals(s.getName()));
                    
                    if (!hasRolesScope) {
                        log.info("Ajout du scope 'roles' au client...");
                        clientResource.addDefaultClientScope(rolesScope.get().getId());
                        log.info("✓ Scope 'roles' ajouté au client");
                    } else {
                        log.debug("Scope 'roles' déjà présent sur le client");
                    }
                } else {
                    log.warn("Scope 'roles' non trouvé dans les scopes par défaut du realm");
                }
            } catch (Exception e) {
                log.warn("Erreur lors de l'ajout du scope 'roles': {}", e.getMessage());
            }
            
            // Le scope "roles" de Keycloak crée automatiquement realm_access.roles
            // Pas besoin de mapper personnalisé si on utilise realm_access.roles
            // Le mapper personnalisé peut créer des conflits (comme dans unionflow)
            log.debug("Le scope 'roles' est utilisé pour créer realm_access.roles automatiquement");
        } catch (Exception e) {
            log.warn("Erreur lors de la vérification/création du client: {}", e.getMessage(), e);
        }
    }

    private String getCreatedId(jakarta.ws.rs.core.Response response) {
        jakarta.ws.rs.core.Response.StatusType statusInfo = response.getStatusInfo();
        if (statusInfo.equals(jakarta.ws.rs.core.Response.Status.CREATED)) {
            String location = response.getLocation().getPath();
            return location.substring(location.lastIndexOf('/') + 1);
        }
        throw new RuntimeException("Erreur lors de la création: " + statusInfo.getStatusCode());
    }
}

