# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later

from django.core.management import BaseCommand
from django.db.models import Sum, F

from note.models import Note, Transaction
from note.templatetags.pretty_money import pretty_money


class Command(BaseCommand):
    def add_arguments(self, parser):
        parser.add_argument('--sum-all', '-s', action='store_true', help='Check if the global sum is equal to zero')
        parser.add_argument('--check-all', '-a', action='store_true', help='Check all notes')
        parser.add_argument('--check', '-c', type=int, nargs='+', help='Select note ids')
        parser.add_argument('--fix', '-f', action='store_true', help='Fix note balances')

    def handle(self, *args, **options):
        error = False
        err_log = ""

        if options["sum_all"]:
            s = Note.objects.aggregate(Sum("balance"))["balance__sum"]
            if s:
                self.stderr.write(self.style.NOTICE("LA SOMME DES NOTES NE VAUT PAS ZÉRO : " + pretty_money(s)))
                error = True
            else:
                if options["verbosity"] > 0:
                    self.stdout.write(self.style.SUCCESS("La somme des notes vaut bien zéro."))

        notes = Note.objects.none()
        if options["check_all"]:
            notes = Note.objects.all()
        elif options["check"]:
            notes = Note.objects.filter(pk__in=options["check"])

        for note in notes:
            balance = note.balance
            incoming = Transaction.objects.filter(valid=True, destination=note)\
                .annotate(total=F("quantity") * F("amount")).aggregate(Sum("total"))["total__sum"] or 0
            outcoming = Transaction.objects.filter(valid=True, source=note)\
                .annotate(total=F("quantity") * F("amount")).aggregate(Sum("total"))["total__sum"] or 0
            calculated_balance = incoming - outcoming
            if calculated_balance != balance:
                self.stderr.write(self.style.NOTICE(f"LA SOMME DES TRANSACTIONS DE LA NOTE {note} NE CORRESPOND PAS "
                                                    "AVEC LE MONTANT RÉEL"))
                self.stderr.write(self.style.NOTICE(f"Attendu : {pretty_money(balance)}, "
                                                    f"calculé : {pretty_money(calculated_balance)}"))
                if options["fix"]:
                    note.balance = calculated_balance
                    note.save()
                error = True

        exit(1 if error else 0)