#!/usr/share/ucs-test/runner python
## -*- coding: utf-8 -*-
## desc: Test creation of usernames from a special username scheme (Bug #41243, #41244)
## tags: [apptest,ucsschool,skip_in_multiserver,ucsschool_import]
## roles: [domaincontroller_master]
## exposure: dangerous
## packages:
##   - ucs-school-import
## bugs: [41243, 41244]

import copy
import pprint
from ldap.filter import escape_filter_chars
import univention.testing.strings as uts
import univention.testing.utils as utils
from univention.testing.ucs_samba import wait_for_drs_replication
from essential.importusers_cli_v2 import CLI_Import_v2_Tester
from essential.importusers import Person


class Test(CLI_Import_v2_Tester):

	def __init__(self):
		super(Test, self).__init__()
		self.ou_B = None
		self.ou_C = None

	def test(self):  # formerly test_create_with_username_scheme()
		"""
		Test creation of usernames from a special username scheme (Bug #41243, #41244).
		"""
		for role in ('student', 'teacher', 'staff', 'teacher_and_staff'):
			for scheme in ["ALWAYSCOUNTER", "COUNTER2"]:
				self.log.info('*** Importing a new single user with role %r, username scheme %r and recordUID 1. time', role, scheme)

				source_uid = 'sourceUID-%s' % (uts.random_string(),)
				record_uid = uts.random_name()

				config = copy.deepcopy(self.default_config)
				config.update_entry('sourceUID', source_uid)
				config.update_entry('csv:mapping:DBID', 'record_uid')
				config.update_entry('scheme:recordUID', '<record_uid>')
				config.update_entry('user_role', role)
				config.update_entry('scheme:username:default', "<:umlauts>user-<firstname>[0:2].<lastname>[0:2]-[{}]".format(scheme))

				person = Person(self.ou_A.name, role)
				person.update(record_uid=record_uid, source_uid=source_uid, username=None)
				fn_csv = self.create_csv_file(person_list=[person], mapping=config['csv']['mapping'])
				config.update_entry('input:filename', fn_csv)
				fn_config = self.create_config_json(config=config)
				# save ldap state for later comparison
				self.save_ldap_status()

				# start import
				self.run_import(['-c', fn_config, '-i', fn_csv])

				# update dn+username of person and verify LDAP attributes
				new_users = [x for x in self.diff_ldap_status().new if x.startswith('uid=')]
				person.update(dn=new_users[0], record_uid=record_uid, source_uid=source_uid)
				wait_for_drs_replication('cn={}'.format(escape_filter_chars(person.username)))

				# check for new users in LDAP
				self.check_new_and_removed_users(1, 0)
				person.verify()

				username_prefix = 'user%s.%s' % (person.firstname[0:2], person.lastname[0:2])
				self.log.info("Calculated username_prefix is %r.", username_prefix)
				if person.username != "{}{}".format(username_prefix, "1" if scheme == "ALWAYSCOUNTER" else ""):
					self.fail('username %r is not expected string "%s%s"' % (person.username, username_prefix, "1" if scheme == "ALWAYSCOUNTER" else ""))
				self.log.info('Username %r is expected with string "%s%s"', person.username, username_prefix, "1" if scheme == "ALWAYSCOUNTER" else "")

				# check if username history object exists
				self.log.info('Checking for unique-usernames object...')
				dn = 'cn=%s,cn=unique-usernames,cn=ucsschool,cn=univention,%s' % (username_prefix, self.lo.base)
				attrs = {
					'objectClass': ['ucsschoolUsername'],
					'ucsschoolUsernameNextNumber': ['2'],
					'cn': [username_prefix],
				}
				utils.verify_ldap_object(dn, expected_attr=attrs, strict=True, should_exist=True)
				self.log.debug('unique-usernames object %r:\n%s', dn, pprint.PrettyPrinter(indent=2).pformat(self.lo.get(dn)))
				self.log.info('unique-usernames object has been found and is correct.')

				for ext in [2, 3]:
					self.log.info('*** Deleting user with role %r and username and recordUID %d. time', role, ext - 1)
					fn_csv = self.create_csv_file(person_list=[], mapping=config['csv']['mapping'])
					config.update_entry('input:filename', fn_csv)
					fn_config = self.create_config_json(config=config)
					self.save_ldap_status()
					self.run_import(['-c', fn_config, '-i', fn_csv])
					utils.wait_for_replication()
					person.set_mode_to_delete()
					self.check_new_and_removed_users(0, 1)
					person.verify()

					self.log.info('*** Importing same user with role %r with same username and recordUID %d. time', role, ext)
					person.update(record_uid=record_uid, source_uid=source_uid, username=None, mode='A')
					fn_csv = self.create_csv_file(person_list=[person], mapping=config['csv']['mapping'])
					config.update_entry('input:filename', fn_csv)
					fn_config = self.create_config_json(config=config)
					self.save_ldap_status()
					self.run_import(['-c', fn_config, '-i', fn_csv])
					utils.wait_for_replication()
					new_users = [x for x in self.diff_ldap_status().new if x.startswith('uid=')]
					person.update(dn=new_users[0], record_uid=record_uid, source_uid=source_uid)
					wait_for_drs_replication('cn={}'.format(escape_filter_chars(person.username)))
					self.check_new_and_removed_users(1, 0)

					person.verify()
					if person.username != "{}{}".format(username_prefix, ext):
						self.fail('username %r is not expected string "%s%d"' % (person.username, username_prefix, ext))
					self.log.info('Username %r is expected with string "%s%d', person.username, username_prefix, ext)

					self.log.info('Checking for unique-usernames object...')
					dn = 'cn=%s,cn=unique-usernames,cn=ucsschool,cn=univention,%s' % (username_prefix, self.lo.base)
					attrs = {
						'objectClass': ['ucsschoolUsername'],
						'ucsschoolUsernameNextNumber': [str(ext + 1)],
						'cn': [username_prefix],
					}
					self.log.info('unique-usernames object is correct.')


def main():
	tester = Test()
	try:
		tester.run()
	finally:
		tester.cleanup()


if __name__ == '__main__':
	main()
