
"""
Crée des opérations aléatoires réparties sur une période de temps spécifiée
"""

import random
from datetime import timedelta
from decimal import Decimal
from django.utils import timezone
from django.core.management.base import BaseCommand

from kfet.models import (Account, Article, OperationGroup, Operation,
                         Checkout, Transfer, TransferGroup)


class Command(BaseCommand):
    help = "Crée des opérations réparties uniformément sur une période de temps"

    def add_arguments(self, parser):
        # Nombre d'opérations à créer
        parser.add_argument('opes', type=int,
                            help='Number of opegroups to create')

        # Période sur laquelle créer (depuis num_days avant maintenant)
        parser.add_argument('days', type=int,
                            help='Period in which to create opegroups')

        # Optionnel : nombre de transfert à créer (défaut 0)
        parser.add_argument('--transfers', type=int, default=0,
                            help='Number of transfers to create (default 0)')


    def handle(self, *args, **options):

        self.stdout.write("Génération d'opérations")

        # Output log vars
        opes_created = 0
        purchases = 0
        transfers = 0

        num_ops = options['opes']
        num_transfers = options['transfers']
        # Convert to seconds
        time = options['days'] * 24 * 3600

        checkout = Checkout.objects.first()
        articles = Article.objects.all()
        accounts = Account.objects.exclude(trigramme='LIQ')
        liq_account = Account.objects.get(trigramme='LIQ')
        try:
            con_account = Account.objects.get(
                cofprofile__user__first_name='Assurancetourix'
            )
        except Account.DoesNotExist:
            con_account = random.choice(accounts)

        for i in range(num_ops):

            # Randomly pick account
            if random.random() > 0.25:
                account = random.choice(accounts)
            else:
                account = liq_account

            # Randomly pick time
            at = timezone.now() - timedelta(
                seconds=random.randint(0, time))

            # Majoration sur compte 'concert'
            if random.random() < 0.2:
                addcost = True
                addcost_for = con_account
                addcost_amount = Decimal('0.5')
            else:
                addcost = False

            # Initialize opegroup amount
            amount = Decimal('0')

            opegroup = OperationGroup.objects.create(
                on_acc=account,
                checkout=checkout,
                at=at,
                is_cof=account.cofprofile.is_cof
            )

            # Generating operations
            ope_list = []
            for j in range(random.randint(1, 4)):
                # Operation type
                typevar = random.random()

                # 0.1 probability to have a charge
                if typevar > 0.9 and account != liq_account:
                    ope = Operation(
                        group=opegroup,
                        type=Operation.DEPOSIT,
                        is_checkout=(random.random() > 0.2),
                        amount=Decimal(random.randint(1, 99)/10)
                    )
                # 0.1 probability to have a withdrawal
                elif typevar > 0.8 and account != liq_account:
                    ope = Operation(
                        group=opegroup,
                        type=Operation.WITHDRAW,
                        is_checkout=(random.random() > 0.2),
                        amount=-Decimal(random.randint(1, 99)/10)
                    )
                else:
                    article = random.choice(articles)
                    nb = random.randint(1, 5)

                    ope = Operation(
                        group=opegroup,
                        type=Operation.PURCHASE,
                        amount=-article.price*nb,
                        article=article,
                        article_nb=nb
                    )

                    purchases += 1

                    if addcost:
                        ope.addcost_for = addcost_for
                        ope.addcost_amount = addcost_amount * nb
                        ope.amount -= ope.addcost_amount

                ope_list.append(ope)
                amount += ope.amount

            Operation.objects.bulk_create(ope_list)
            opes_created += len(ope_list)
            opegroup.amount = amount
            opegroup.save()

        # Transfer generation
        for i in range(num_transfers):

            # Randomly pick time
            at = timezone.now() - timedelta(
                seconds=random.randint(0, time))

            # Choose whether to have a comment
            if random.random() > 0.5:
                comment = "placeholder comment"
            else:
                comment = ""

            transfergroup = TransferGroup.objects.create(
                at=at,
                comment=comment,
                valid_by=random.choice(accounts)
            )

            # Randomly generate transfer
            transfer_list = []
            for i in range(random.randint(1, 4)):
                transfer_list.append(Transfer(
                    group=transfergroup,
                    from_acc=random.choice(accounts),
                    to_acc=random.choice(accounts),
                    amount=Decimal(random.randint(1, 99)/10)
                ))

            Transfer.objects.bulk_create(transfer_list)
            transfers += len(transfer_list)

        self.stdout.write(
            "- {:d} opérations créées dont {:d} commandes d'articles"
            .format(opes_created, purchases))

        if transfers:
            self.stdout.write("- {:d} transferts créés"
                              .format(transfers))
