# barbacompta - invoicing for dummies
# Copyright (C) 2019-2020 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import uuid
from datetime import date
from decimal import Decimal

from eo_gestion.eo_facture.models import Client, Contrat, Facture


def test_contrat_montant_par_annee_percentage_per_year(db, django_user_model, freezer):
    freezer.move_to('2021-06-01')
    client = Client.objects.create(nom=str(uuid.uuid4()))
    user = django_user_model.objects.all()[0]
    contrat = Contrat.objects.create(
        client=client,
        creator=user,
        intitule=str(uuid.uuid4()),
        percentage_per_year=[(2020, Decimal(0.5)), (2021, Decimal(0.25)), (2022, Decimal(0.25))],
    )
    contrat.clean()
    for i in range(10):
        contrat.prestations.create(intitule=str(i), quantite=1, prix_unitaire_ht=1000)

    facture = Facture.objects.create(
        proforma=False,
        client=client,
        contrat=contrat,
        emission=date(2020, 1, 1),
        echeance=date(2020, 1, 16),
        creator=user,
    )
    facture.lignes.create(prix_unitaire_ht=1000, quantite=1, order=1)

    facture = Facture.objects.create(
        proforma=False,
        client=client,
        contrat=contrat,
        emission=date(2021, 1, 1),
        echeance=date(2021, 1, 16),
        creator=user,
    )
    facture.lignes.create(prix_unitaire_ht=1000, quantite=1, order=1)

    assert sorted(list(contrat.montant_par_annee().items())) == [(2021, Decimal(5500)), (2022, Decimal(2500))]


def test_contrat_montant_par_annee_recurrent(db, django_user_model, freezer):
    freezer.move_to('2021-06-01')
    client = Client.objects.create(nom=str(uuid.uuid4()))
    user = django_user_model.objects.all()[0]
    contrat = Contrat.objects.create(
        client=client,
        creator=user,
        intitule=str(uuid.uuid4()),
        periodicite='semestrielle',
        periodicite_debut=date(2020, 7, 1),
        periodicite_fin=date(2023, 7, 1),
    )
    contrat.clean()
    for i in range(2):
        contrat.prestations.create(intitule=str(i), quantite=1, prix_unitaire_ht=1000)

    facture = Facture.objects.create(
        proforma=False,
        client=client,
        contrat=contrat,
        emission=date(2020, 1, 1),
        echeance=date(2020, 1, 16),
        creator=user,
    )
    facture.lignes.create(prix_unitaire_ht=1000, quantite=1, order=1)

    facture = Facture.objects.create(
        proforma=False,
        client=client,
        contrat=contrat,
        emission=date(2021, 1, 1),
        echeance=date(2021, 1, 16),
        creator=user,
    )
    facture.lignes.create(prix_unitaire_ht=1000, quantite=1, order=1)

    assert contrat.montant() == Decimal(1000) * 2 * 6
    assert sorted(list(contrat.montant_par_annee().items())) == [
        (2021, Decimal(4000)),
        (2022, Decimal(4000)),
        (2023, Decimal(2000)),
    ]


def test_facture_avoir_sur_contrat_recurrent(db, django_user_model, freezer):
    freezer.move_to('2021-06-01')
    client = Client.objects.create(nom=str(uuid.uuid4()))
    user = django_user_model.objects.all()[0]
    contrat = Contrat.objects.create(
        client=client,
        creator=user,
        intitule=str(uuid.uuid4()),
        periodicite='semestrielle',
        periodicite_debut=date(2020, 7, 1),
        periodicite_fin=date(2023, 7, 1),
    )
    contrat.clean()
    for i in range(2):
        contrat.prestations.create(intitule=str(i), quantite=1, prix_unitaire_ht=1000)

    # facture récurrente : code from admin.py::facturer_echeance
    numero = None
    for i, debut, _ in contrat.periodicite_echeances():
        if i == 1:  # échéance
            numero = i
            break
    facture1, _ = Facture.objects.update_or_create(
        client=contrat.client,
        contrat=contrat,
        echeance=debut,
        numero_d_echeance=numero,
        defaults={
            'creator': user,
            'numero_d_echeance': numero,
        },
    )

    # création d'un avoir sur une facture récurrente
    avoir1 = facture1.cancel(user)

    # création d'un avoir sur une seconde facture récurrente
    numero = None
    for i, debut, _ in contrat.periodicite_echeances():
        if i == 2:  # échéance
            numero = i
            break
    facture2, _ = Facture.objects.update_or_create(
        client=contrat.client,
        contrat=contrat,
        echeance=debut,
        numero_d_echeance=numero,
        defaults={
            'creator': user,
            'numero_d_echeance': numero,
        },
    )
    avoir2 = facture2.cancel(user)

    assert avoir1.annulation == facture1
    assert avoir2.annulation == facture2
