#!/usr/bin/python3

import sys

from lib.paheko import Paheko
from lib.ldap import Ldap
from lib.ssh import Ssh
from lib.misc import get_disk_size

paheko = Paheko()
categorie_membres = paheko.get_categorie_id("Membres")
membres = paheko.get_users_in_categorie(categorie_membres)
categorie_collegiale = paheko.get_categorie_id("Collégiale")
membres += paheko.get_users_in_categorie(categorie_collegiale)
categorie_administrateurs = paheko.get_categorie_id("Administrateurs")
membres += paheko.get_users_in_categorie(categorie_administrateurs)


def test_services(paheko_entry, ldap_entry):
    # Vérifie que les services orga activés sont bien désactivés sur le mutu. Juste nextcloud pour l'instant.
    is_orga = paheko_entry["admin_orga"].strip("'") == "Oui"
    if is_orga:
        paheko_has_cloud = paheko_entry["cloud"].strip("'") == "Oui"
        ldap_cloud_enabled = ldap_entry[1]['nextcloudEnabled'][0] == b"TRUE"
        # if (paheko_has_cloud and ldap_cloud_enabled):
        #     path = f"/var/lib/docker/volumes/cloud_cloudData/_data/{ldap_entry[1]['identifiantKaz'][0].decode()}"
        #     size = get_disk_size(path)
        #     if size < 40529249:
        #         print(f"{ldap_entry[1]['identifiantKaz'][0].decode()} {size}")
        #         with Ldap() as ldap:
        #             print(ldap_entry[1]['mail'][0].decode())
        #             ldap.update_user(ldap_entry[1]['mail'][0].decode(), "nextcloudEnabled", b"FALSE")
        return not (paheko_has_cloud and ldap_cloud_enabled)

    return True

def test_quota(paheko_entry, ldap_entry):
    quota_paheko = int(paheko_entry["quota_disque"].strip("'"))
    quota_nextcloud = int(ldap_entry[1]['nextcloudQuota'][0][:-3])
    quota_mail = int(ldap_entry[1]['mailQuota'][0][:-1])
    quota_global = int(ldap_entry[1]['quota'][0])
    is_orga = paheko_entry["admin_orga"].strip("'") == "Oui"
    has_mail = ldap_entry[1]['mailEnabled'][0] == b"TRUE"
    has_nextcloud = ldap_entry[1]['nextcloudEnabled'][0] == b"TRUE"
    email = ldap_entry[1]["mail"][0].decode()
    res = ""

    if quota_paheko != quota_global:
        #print(f"{email}: bad quota Paheko/LDAP")
        #ldap.update_user(email, "quota", str(quota_paheko).encode())
        return "Quota paheko et ldap non égaux"

    quota_allowed = quota_paheko + 1 # 1GB pour email

    quota_given = 0
    if has_mail:
        quota_given += quota_mail
    if has_nextcloud:
        quota_given += quota_nextcloud

    # if quota_mail > 1:
    #     localpart, domain = email.split('@',1)
    #     path = f"/var/lib/docker/volumes/postfix_mailData/_data/{domain}/{localpart}"
    #     size = get_disk_size(path)
    #     print(f"email space: {email} {size}")
    #     # if size < 973741824:
    #     #     print(f"{email} {size}")
    #     #     ldap.update_user(email, "mailQuota", b"1G")


    if is_orga:
        linked_emails = paheko_entry["emails_rattaches"]
        if linked_emails:
            for linked_email in linked_emails.splitlines():
                quota_allowed += 1 # 1GB par email rattaché
                ldap_linked_entry = ldap.get_email(linked_email)
                if ldap_linked_entry:
                    quota_given += int(ldap_linked_entry[0][1]['mailQuota'][0][:-1])

    # beaucoup ont en fait xGO de mail et xGO de cloud pour xGO en tout, à corriger à terme.
    # if quota_global * 2 == quota_given or 1 + quota_global * 2 == quota_given:
    #    return True

    # On laisse 1GO de rab' pour tous ceux qui ont 10 de cloud et 1 de mail.
    #if quota_given <= quota_global + 1:
    #    return True

    # Si cloud dédié, aller chercher la place utilisée sur le cloud dédié ! + wordpress
    if is_orga and (paheko_entry["cloud"].strip("'") == "Oui"):
        serveur_prod = paheko_entry["serveur_prod"]
        if not serveur_prod:
            return "Pas de serveur prod renseigné"
        directory = f"/var/lib/docker/volumes/orga_{paheko_entry['nom_orga'].lower()}-cloudData"
        with Ssh(serveur_prod) as ssh:
            try:
                nc_size = int(ssh.check_output(f"du -sm {directory} | cut -f1"))
                # print(f"NC {paheko_entry['nom_orga']} - {nc_size}")
                quota_given += nc_size // 1024
                res += f", NC: {nc_size}Mo"
            except ValueError:
                return "erreur taille NC"

    if is_orga and (paheko_entry["wordpress"].strip("'") == "Oui"):
        serveur_prod = paheko_entry["serveur_prod"]
        if not serveur_prod:
            return "Pas de serveur prod renseigné"
        directory = f"/var/lib/docker/volumes/orga_{paheko_entry['nom_orga'].lower()}-wordpress/_data/wp-content"
        with Ssh(serveur_prod) as ssh:
            try:
                wp_size = int(ssh.check_output(f"du -sm {directory} | cut -f1"))
                # print(f"WP {paheko_entry['nom_orga']} - {wp_size}")
                quota_given += wp_size // 1024
                res += f", WP: {wp_size}Mo"
            except ValueError:
                return "erreur taille WP"

    if quota_given > quota_allowed:
        # print(f"{ldap_entry[1]['mail'][0].decode()}: {quota_given}/{quota_allowed}")
        res += f" -> utilise {quota_given} (max {quota_allowed})"
        print(f"{email}: {res}")
        return res


def test_mail_secours(paheko_entry, ldap_entry):
    # Vérifie que le mail de secours dans le LDAP correspond à celui dans paheko.
    if paheko_entry["email_secours"]:
        return paheko_entry["email_secours"].strip("'").encode() == ldap_entry[1]['mailDeSecours'][0]
    else:
        return False


def test_mails_orga(paheko_entry):
    # Vérifie que les mails des orgas sont bien dans le LDAP.
    is_orga = paheko_entry["admin_orga"].strip("'") == "Oui"
    res = []
    if is_orga:
        linked_emails = paheko_entry["emails_rattaches"]
        if linked_emails:
            for linked_email in linked_emails.splitlines():
                ldap_linked_entry = ldap.get_email(linked_email)
                if not ldap_linked_entry:
                    res.append(linked_email)
    return res


def test_server_location(paheko_entry):
    # Vérifie que le serveur est bien renseigné.
    is_orga = paheko_entry["admin_orga"].strip("'") == "Oui"
    if is_orga and (paheko_entry["cloud"].strip("'") == "Oui" or paheko_entry["wordpress"].strip("'") == "Oui"):
        serveur_prod = paheko_entry["serveur_prod"]
        if not serveur_prod:
            return False
        directory = f"/kaz/dockers/{paheko_entry['nom_orga'].lower()}-orga"
        with Ssh(serveur_prod) as ssh:
            return ssh.check_return_code(f"ls {directory}") == 0
    return True

with Ldap() as ldap:
    try:
        not_in_ldap = []
        not_in_paheko = []
        mail_secours = []
        quota = []
        services = []
        mails_orgas = []
        servers_locations = []
        nextcloud_ldap_wrong = []
        for membre in membres:
            ldap_entry = ldap.get_email(membre["email"])
            if ldap_entry:
                ldap_entry = ldap_entry[0]

                if not test_mail_secours(membre, ldap_entry):
                    mail_secours.append(f"{membre['email']}: Paheko {membre['email_secours']}, LDAP {ldap_entry[1]['mailDeSecours'][0].decode()}")

                if not test_services(membre, ldap_entry):
                    path = f"/var/lib/docker/volumes/cloud_cloudData/_data/{ldap_entry[1]['identifiantKaz'][0].decode()}"
                    size = int(get_disk_size(path) / 1024 / 1024)
                    services.append(f"{membre['email']}: Paheko {membre['cloud']}, LDAP {ldap_entry[1]['nextcloudEnabled'][0].decode()}, espace cloud commun {size}Mo")

                quota_ko = test_quota(membre, ldap_entry)
                if quota_ko :
                    suffix = ""
                    if membre['emails_rattaches']:
                        suffix = " rattachés\n  " + "\n  ".join(membre['emails_rattaches'].splitlines())
                    quota.append(f"{membre['email']}: Paheko {membre['quota_disque']}, LDAP mail {ldap_entry[1]['mailQuota'][0].decode()} cloud {ldap_entry[1]['nextcloudQuota'][0].decode()} quotaGlobal {ldap_entry[1]['quota'][0].decode()} diag {quota_ko} {suffix}")

                mails_orga = test_mails_orga(membre)
                if mails_orga:
                    suffix = '\n  '.join(mails_orga)
                    mails_orgas.append(f"{membre['email']}:\n  {suffix}")

                if not test_server_location(membre):
                    servers_locations.append(f"{membre['email']} - {membre['nom_orga']}, pas trouvé sur {membre['serveur_prod']}")

            else:
                ldap_entry = ldap.get_mail_forwarding(membre["email"])
                if not ldap_entry:
                    not_in_ldap.append(f"{membre['email']} / id : {membre['id']}")
    except Exception as e:
        print(membre)
        print(ldap.get_email(membre["email"]))
        raise e

    ldap_users = ldap.get_users()
    for ldap_user in ldap_users:
        ldap_user = ldap_user[1]
        paheko_entry = [x for x in membres if x["email"] == ldap_user["mail"][0].decode() or (x["emails_rattaches"] and ldap_user["mail"][0].decode() in x["emails_rattaches"])]
        paheko_entry = paheko_entry[0] if len(paheko_entry) else None
        if paheko_entry:
            pass
        else:
            not_in_paheko.append(ldap_user["mail"][0].decode())

        paheko_member = [x for x in membres if x["email"] == ldap_user["mail"][0].decode()]
        paheko_member = paheko_member[0] if len(paheko_member) else None
        if paheko_member or ldap_user["nextcloudEnabled"][0].decode() != "TRUE":
            pass
        else:
            path = f"/var/lib/docker/volumes/cloud_cloudData/_data/{ldap_user['identifiantKaz'][0].decode()}"
            size = int(get_disk_size(path) / 1024 / 1024)
            nextcloud_ldap_wrong.append(f"{ldap_user["mail"][0].decode()}: espace cloud commun {size}Mo")
            #if size < 30:
                #print(f"{ldap_user["mail"][0].decode()} {size}")
                #ldap.update_user(ldap_user["mail"][0].decode(), "nextcloudEnabled", b"FALSE")
                #sys.exit(0)

    ldap_forwardings = ldap.get_mail_forwardings()
    for ldap_user in ldap_forwardings:
        ldap_user = ldap_user[1]
        paheko_entry = [x for x in membres if x["email"] == ldap_user["mailAlias"][0].decode() or (x["forward"] and ldap_user["mailAlias"][0].decode() in x["forward"])]
        paheko_entry = paheko_entry[0] if len(paheko_entry) else None
        if paheko_entry:
            pass
        else:
            not_in_paheko.append(ldap_user["mailAlias"][0].decode() + " (forwarding)")


print("Mails dans paheko mais pas dans le LDAP :")
print("\n".join(not_in_ldap))

print("Mails dans le LDAP mais pas dans paheko :")
print("\n".join(not_in_paheko))

print("\nMails de secours pas ok dans le LDAP :")
print("\n".join(mail_secours))

print("\nServices pas ok dans le LDAP (ont nextcloud commun + dédié) :")
print("\n".join(services))

print("\nQuotas pas ok dans le LDAP :")
print("\n".join(quota))

print("\nMails d'orga dans paheko mais manquant dans le LDAP :")
print("\n".join(mails_orgas))

print("\nOrgas pas trouvées sur le serveur renseigné dans paheko :")
print("\n".join(servers_locations))

print("Comptes LDAP ayant Nextcloud actif à tort :")
print("\n".join(nextcloud_ldap_wrong))
