# barbacompta - invoicing for dummies
# Copyright (C) 2010-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 datetime
import io
import xml.etree.ElementTree as ET

import facturx
import pytest

from eo_gestion.eo_facture.facturx import add_facturx_from_bytes, to_pdfa


@pytest.fixture
def fake_invoice_bytes():
    with open('tests/fake-invoice.pdf', 'rb') as fd:
        return fd.read()


def test_to_pdfa(fake_invoice_bytes):
    to_pdfa(fake_invoice_bytes)


def test_add_facturx_from_bytes(fake_invoice_bytes):
    facturx_ctx = {
        'numero_de_facture': 'F20190001',
        'type_facture': '380',
        'date_emission': datetime.date(2019, 1, 1),
        'chorus_service_code': 'service-code',
        'vendeur': 'Entr\'ouvert',
        'vendeur_siret': '44317013900036',
        'vendeur_tvai': 'FR09491081899',
        'client_siret': '1234',
        'client_name': 'RGFIPD',
        'numero_engagement': '5678',
        'numero_marche': 'ABCD',
        'montant_ht': '10',
        'montant_ttc': '12',
        'montant_tva': '2',
        'taux_tva': 20.0,
    }
    facturx_bytes = add_facturx_from_bytes(fake_invoice_bytes, facturx_ctx)
    _, xml_str = facturx.get_facturx_xml_from_pdf(io.BytesIO(facturx_bytes))
    root = ET.fromstring(xml_str)

    def helper(root):
        tag = root.tag.split('}')[-1]
        if len(root) == 0:
            return [tag, root.text or '']
        else:
            return [tag] + [helper(node) for node in root]

    assert helper(root) == [
        'CrossIndustryInvoice',
        [
            'ExchangedDocumentContext',
            ['BusinessProcessSpecifiedDocumentContextParameter', ['ID', 'A1']],
            ['GuidelineSpecifiedDocumentContextParameter', ['ID', 'urn:factur-x.eu:1p0:basicwl']],
        ],
        [
            'ExchangedDocument',
            ['ID', 'F20190001'],
            ['TypeCode', '380'],
            ['IssueDateTime', ['DateTimeString', '20190101']],
        ],
        [
            'SupplyChainTradeTransaction',
            [
                'ApplicableHeaderTradeAgreement',
                ['BuyerReference', 'service-code'],
                [
                    'SellerTradeParty',
                    ['Name', "Entr'ouvert"],
                    ['SpecifiedLegalOrganization', ['ID', '44317013900036']],
                    ['PostalTradeAddress', ['CountryID', 'FR']],
                    ['SpecifiedTaxRegistration', ['ID', 'FR09491081899']],
                ],
                [
                    'BuyerTradeParty',
                    ['Name', 'RGFIPD'],
                    [
                        'SpecifiedLegalOrganization',
                        ['ID', '1234'],
                    ],
                ],
                ['BuyerOrderReferencedDocument', ['IssuerAssignedID', '5678']],
                ['ContractReferencedDocument', ['IssuerAssignedID', 'ABCD']],
            ],
            ['ApplicableHeaderTradeDelivery', ''],
            [
                'ApplicableHeaderTradeSettlement',
                ['InvoiceCurrencyCode', 'EUR'],
                [
                    'ApplicableTradeTax',
                    ['CalculatedAmount', '2'],
                    ['TypeCode', 'VAT'],
                    ['BasisAmount', '10'],
                    ['CategoryCode', 'S'],
                    ['RateApplicablePercent', '20.0'],
                ],
                [
                    'SpecifiedTradeSettlementHeaderMonetarySummation',
                    ['LineTotalAmount', '10'],
                    ['TaxBasisTotalAmount', '10'],
                    ['TaxTotalAmount', '2'],
                    ['GrandTotalAmount', '12'],
                    ['DuePayableAmount', '12'],
                ],
            ],
        ],
    ]


def test_add_facturx_from_bytes_facture_avoir(fake_invoice_bytes):
    facturx_ctx = {
        'numero_de_facture': 'F20190002',
        'type_facture': '381',
        'date_emission': datetime.date(2019, 1, 1),
        'chorus_service_code': 'service-code',
        'vendeur': 'Entr\'ouvert',
        'vendeur_siret': '44317013900036',
        'vendeur_tvai': 'FR09491081899',
        'client_siret': '1234',
        'client_name': 'RGFIPD',
        'numero_engagement': '5678',
        'numero_marche': 'ABCD',
        'montant_ht': '10',
        'montant_ttc': '12',
        'montant_tva': '2',
        'taux_tva': 20.0,
        'annulation_code': 'F20190001',
    }
    facturx_bytes = add_facturx_from_bytes(fake_invoice_bytes, facturx_ctx)
    _, xml_str = facturx.get_facturx_xml_from_pdf(io.BytesIO(facturx_bytes))
    root = ET.fromstring(xml_str)

    def helper(root):
        tag = root.tag.split('}')[-1]
        if len(root) == 0:
            return [tag, root.text or '']
        else:
            return [tag] + [helper(node) for node in root]

    assert helper(root) == [
        'CrossIndustryInvoice',
        [
            'ExchangedDocumentContext',
            ['BusinessProcessSpecifiedDocumentContextParameter', ['ID', 'A1']],
            ['GuidelineSpecifiedDocumentContextParameter', ['ID', 'urn:factur-x.eu:1p0:basicwl']],
        ],
        [
            'ExchangedDocument',
            ['ID', 'F20190002'],
            ['TypeCode', '381'],
            ['IssueDateTime', ['DateTimeString', '20190101']],
        ],
        [
            'SupplyChainTradeTransaction',
            [
                'ApplicableHeaderTradeAgreement',
                ['BuyerReference', 'service-code'],
                [
                    'SellerTradeParty',
                    ['Name', "Entr'ouvert"],
                    ['SpecifiedLegalOrganization', ['ID', '44317013900036']],
                    ['PostalTradeAddress', ['CountryID', 'FR']],
                    ['SpecifiedTaxRegistration', ['ID', 'FR09491081899']],
                ],
                [
                    'BuyerTradeParty',
                    ['Name', 'RGFIPD'],
                    [
                        'SpecifiedLegalOrganization',
                        ['ID', '1234'],
                    ],
                ],
                ['BuyerOrderReferencedDocument', ['IssuerAssignedID', '5678']],
                ['ContractReferencedDocument', ['IssuerAssignedID', 'ABCD']],
            ],
            ['ApplicableHeaderTradeDelivery', ''],
            [
                'ApplicableHeaderTradeSettlement',
                ['InvoiceCurrencyCode', 'EUR'],
                ['SpecifiedTradeSettlementPaymentMeans', ['TypeCode', '97']],
                [
                    'ApplicableTradeTax',
                    ['CalculatedAmount', '2'],
                    ['TypeCode', 'VAT'],
                    ['BasisAmount', '10'],
                    ['CategoryCode', 'S'],
                    ['RateApplicablePercent', '20.0'],
                ],
                [
                    'SpecifiedTradeSettlementHeaderMonetarySummation',
                    ['LineTotalAmount', '10'],
                    ['TaxBasisTotalAmount', '10'],
                    ['TaxTotalAmount', '2'],
                    ['GrandTotalAmount', '12'],
                    ['DuePayableAmount', '12'],
                ],
                ['InvoiceReferencedDocument', ['IssuerAssignedID', 'F20190001']],
            ],
        ],
    ]
