#!/usr/bin/python3

import csv
from ast import literal_eval
from ldap import MOD_REPLACE, MOD_ADD

from scribe.eolegroup import Group
from scribe.eleves import Eleve
from scribe.enseignants import Enseignant
from scribe.administratifs import Administratif
from scribe.ldapconf import MAIL_DOMAIN, num_etab
from pyeole.ansiprint import print_red
from pyeole.process import system_out

group = Group()
group.ldap_admin.connect()

REVERSE_MAIL_DOMAIN = {value: key for key, value in MAIL_DOMAIN.items()}
shares = {}
users_group = {}
groups_dn = {}
ret_code = 0

def get_etab(dn):
    etab = dn.split('=', -1)[-1]
    if etab == num_etab:
        etab = None
    return etab

with open('shares.csv', 'r') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        shares[row['sambaShareName']] = get_etab(row['dn'])

with open('groups.csv', 'r') as csvfile:
    reader = csv.DictReader(csvfile)
    groups = {'level': [],
              'other': [],
              }
    for row in reader:
        if row['memberUid']:
            members = row['memberUid']
            if not isinstance(members, list):
                if members.startswith('['):
                    members = literal_eval(members)
                else:
                    members = [members]
            for member in members:
                users_group.setdefault(member, []).append(row['cn'])

        if row['type'] in ['', 'Equipe', 'Base']:
            continue
        group_info = {'_type': row['type'],
                      'name': row['cn'],
                      'description': row['description'],
                      'mkdir': False,
                      }
        if row['mail']:
            group_info['domaine'] = REVERSE_MAIL_DOMAIN[row['mail'].split('@')[-1]]
        if row['niveau']:
            group_info['niveau'] = row['niveau']
        if row['cn'] in shares:
            # les répertoires ne sont pas créer (mkdir=False) peut importe la valeur
            group_info['partage'] = 'ro'
            if shares[row['cn']]:
                group_info['etab'] = shares[row['cn']]
        if row['type'] == 'Niveau':
            groups['level'].append(group_info)
        else:
            groups['other'].append(group_info)
    # create levels before classes
    for row in groups['level']:
        try:
            group._add(**row)
            groups_dn[row['name']] = group.get_group_dn(row['name'])
        except Exception as err:
            print_red(f'impossible de créer {row["name"]} : {err}')
            ret_code = 1
            try:
                groups_dn[row['name']] = group.get_group_dn(row['name'])
            except:
                pass
    for row in groups['other']:
        try:
            group._add(**row)
            groups_dn[row['name']] = group.get_group_dn(row['name'])
        except Exception as err:
            print_red(f'impossible de créer {row["name"]} : {err}')
            ret_code = 1
            try:
                groups_dn[row['name']] = group.get_group_dn(row['name'])
            except:
                pass

eleve = Eleve()
eleve.ldap_admin = group.ldap_admin
enseignant = Enseignant()
enseignant.ldap_admin = group.ldap_admin
administratif = Administratif()
administratif.ldap_admin = group.ldap_admin
with open('users.csv', 'r') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        if row['ENTPersonProfils'] == 'eleve':
            obj = eleve
        elif row['ENTPersonProfils'] == 'enseignant':
            obj = enseignant
        elif row['ENTPersonProfils'] == 'administratif':
            obj = administratif
        else:
            print_red(f"Type d'utilisateur {row['ENTPersonProfils']} pour l'utilisateur {row['cn']}")
            ret_code = 1
        user_obj = {'login': row['uid'],
                    'shell': row['loginShell'],
                    'etab': get_etab(row['dn']),
                    # for enseignant
                    'admin': False,
                    'groups': users_group.get(row['cn'], []),
                    # for eleves
                    'classe': row['Divcod'],
                    }
        # for administratifs
        user_obj['groupe'] = user_obj['groups']
        if row['sambaProfilePath']:
            partage, profilname = row['sambaProfilePath'].split('\\')[3:5]
            if partage != 'netlogon':
                profil = 4
            elif profilname == 'profil':
                profil = 2
            else:
                profil = 3
        else:
            profil = 0
        user_obj['profil'] = profil
        if user_obj['login'] != 'admin':
            try:
                user_add_args = obj.get_smbldap_useradd_args(**user_obj)
                obj.exec_smbldap_useradd(user_add_args, user_obj['login'])
            except Exception as err:
                print_red(f"Erreur à la création de l'utilisateur {user_obj['login']} : {err}")
                ret_code = 1
                continue
        try:
            user_dn = obj.get_user_dn(user_obj['login'])
        except:
            print_red(f"Impossible de retrouver l'utilisateur {user_obj['login']}")
            ret_code = 1
            continue
        datas = []
        for key, value in row.items():
            if key in ['dn', 'cn']:
                continue
            if value.startswith('['):
                try:
                    value = literal_eval(value)
                except:
                    pass
            if value:
                datas.append((MOD_REPLACE, key, value))
        if row['ENTPersonProfils'] == 'eleve':
            for group in user_obj['groups']:
                if group in groups_dn:
                    datas.append((MOD_ADD, 'memberOf', groups_dn['group']))
        try:
            obj.ldap_admin._modify(user_dn, datas)
        except Exception as err:
            print_red(f"Impossible de mettre à jour l'utilisateur {user_obj['login']} : {err}")
            ret_code = 1
            continue
        # update password
        code, out, err = system_out(['pdbedit', '-u', user_obj['login'], '--set-nt-hash', row['sambaNTPassword']], container='domaine')
        if code:
            print_red(f"Impossible de mettre à jour le mot de passe de l'utilisateur {user_obj['login']} : {out} : {err}")


exit(ret_code)
