#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Univention AD Connector
#  List all rejected objects
#
# Like what you see? Join us!
# https://www.univention.com/about-us/careers/vacancies/
#
# Copyright 2004-2024 Univention GmbH
#
# https://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <https://www.gnu.org/licenses/>.


from __future__ import print_function

import argparse
import sys
import textwrap

import ldap

import univention
import univention.config_registry
import univention.connector
import univention.connector.ad


def parse_args():
    parser = argparse.ArgumentParser(
        description="Summarize objects rejected due to sync failures.",
        add_help=True
    )

    parser.add_argument(
        "-c", "--configbase",
        default="connector",
        help='Configuration base to use (default: "connector")'
    )

    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="Enable verbose output"
    )

    return parser.parse_args()


def main():
    args = parse_args()
    configRegistry = univention.config_registry.ConfigRegistry()
    configRegistry.load()

    ad = univention.connector.ad.ad.main(configRegistry, args.configbase)
    max_retry_rejected = configRegistry.get('%s/ad/max_retry_rejected' % (args.configbase,), 10)
    try:
        ad.init_ldap_connections()
    except ldap.SERVER_DOWN as exc:
        print('WARNING: LDAP server could not be reached: %s' % (exc,), file=sys.stderr)
        sys.exit(1)

    found_rejected = False
    i = 1
    print("\nUCS rejected\n")
    for filename, dn in ad.list_rejected_ucs():
        found_rejected = True
        print("%5d:   UCS DN: %s" % (i, dn))
        ad_dn = ad.get_dn_by_ucs(dn)
        if ad_dn:
            print("          AD DN: %s" % ad_dn)
        else:
            print("          AD DN: <not found>")
        print("         Filename: %s\n" % filename)
        i += 1

    i = 1
    print("\nAD rejected\n")
    for _id, dn, retry_count in ad.list_rejected():
        found_rejected = True
        print("%5d:    AD DN: %s" % (i, dn))
        ucs_dn = ad.get_dn_by_con(dn)
        reason = ad._get_reject_reason(_id)
        if ucs_dn:
            print("         UCS DN: %s" % ucs_dn)
        else:
            print("         UCS DN: <not found>")
        try:
            print("         Reason: %s" % reason.splitlines()[0])
        except IndexError:
            # No reason stored in DB
            pass
        if args.verbose:
            try:
                print(textwrap.indent("%s" % "\n".join(reason.splitlines()[1:]), 17 * " "))
            except IndexError:
                # Single line reason
                pass
        print("         tried: %s/%s times\n" % (retry_count, max_retry_rejected))
        i += 1

    if not found_rejected:
        print("\nThere may be no rejected DNs if the connector is in progress, to be\nsure stop the connector before running this script.\n")

    print("\n\tlast synced USN: %s" % ad.get_lastUSN())


if __name__ == "__main__":
    main()
