#!/usr/bin/python3
# Univention Keycloak
#
# SPDX-FileCopyrightText: 2022-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only

import json
import subprocess

from univention.admin.uldap import getMachineConnection
from univention.config_registry import ucr


print('fixing duplicate UID mappers in UMC SAML clients...')

lo, _ = getMachineConnection()

ldap_search_result = lo.search(filter='univentionService=Univention Management Console', attr=['displayName'])

for umc in ldap_search_result:
    umc = umc[1]['displayName'][0].decode('utf-8')

    saml_client_name = f'https://{umc}.{ucr["domainname"]}/univention/saml/metadata'
    try:
        saml_clients_json = subprocess.run(['univention-keycloak', 'saml/sp', 'get', '--json', '--client-id', saml_client_name, '--all'], check=True, capture_output=True)
    except subprocess.CalledProcessError as err:
        print(f'univention-keycloak saml/sp get failed for saml client with name {saml_client_name}: {err}')
        continue

    saml_clients = json.loads(saml_clients_json.stdout)

    try:
        saml_client = saml_clients[0]
    except IndexError:
        print(f'No SAML client found in keycloak for client ID {saml_client_name}')
        continue

    protocol_mappers = saml_client.get('protocolMappers', [])

    uid_protocol_mappers = [
        mapper
        for mapper in protocol_mappers
        if mapper.get('config', {}).get('attribute.name', '') == 'urn:oid:0.9.2342.19200300.100.1.1' or mapper.get('config', {}).get('friendly.name', '') == 'uid'
    ]

    if len(uid_protocol_mappers) <= 1:
        continue

    updated_protocol_mappers = [mapper for mapper in protocol_mappers if mapper.get('name', '') != 'userid_mapper']

    if len(protocol_mappers) == len(updated_protocol_mappers):
        continue

    saml_client['protocolMappers'] = updated_protocol_mappers

    updated_client_json = json.dumps(saml_client)

    try:
        subprocess.run(['univention-keycloak', 'saml/sp', 'update', saml_client_name, updated_client_json], check=True)
    except subprocess.CalledProcessError as err:
        print(f'univention-keycloak saml/sp update failed for saml client with name {saml_client_name}: {err}')
