import json
import os
from datetime import datetime
from decimal import Decimal
from unittest import mock

from satcfdi.create import Issuer
from satcfdi.pacs import Environment
from satcfdi.pacs.diverza import Diverza
from satcfdi.create.cfd import cfdi33, cfdi40, pago20
from tests.utils import get_signer, verify_result

current_dir = os.path.dirname(__file__)
module = 'satcfdi'


def test_diverza_validate_rfc():
    diverza = Diverza(
        rfc="AAA010101AAA",
        id="3935",
        token="ABCD1234"
    )

    with mock.patch(f'requests.request') as mk:
        mk.return_value.json = mock.Mock(return_value={'identifiers': [{'rfc': 'AAA010101AAA', 'active': 'Y'}]})
        
        r = diverza.rfc_valid("AAA010101AAA")
        assert r

    with mock.patch(f'requests.request') as mk:
        mk.return_value.json = mock.Mock(return_value={'identifiers': [{'rfc': 'AAA010101AAA', 'active': 'Y'}, {'rfc': 'ABC010101DAS', 'active': 'N'}]})
        
        r = diverza.rfc_valid(["AAA010101AAA", "ABC010101DAS"])

        assert r[0]
        assert not r[1]


def test_diverza_stamp():
    signer = get_signer('xiqb891116qe4')
    emisor = Issuer(signer=signer, tax_system="601")

    diverza = Diverza(
        rfc="AAA010101AAA",
        id="3935",
        token="ABCD1234",
        environment=Environment.TEST
    )

    cfdi = cfdi33.Comprobante(
        emisor=emisor,
        lugar_expedicion="56820",
        fecha=datetime.fromisoformat("2022-09-28T22:40:38"),
        receptor=cfdi33.Receptor(
            rfc='KIJ0906199R1',
            nombre='KIJ, S.A DE C.V.',
            uso_cfdi='G03'
        ),
        metodo_pago='PPD',
        serie="A",
        folio="123456",
        conceptos=[
            cfdi33.Concepto(
                cuenta_predial='1234567890',
                clave_prod_serv='10101702',
                cantidad=Decimal('1.00'),
                clave_unidad='E48',
                descripcion='SERVICIOS DE FACTURACION',
                valor_unitario=Decimal('15390.30'),
                impuestos=cfdi33.Impuestos(
                    traslados=cfdi33.Impuesto.parse('002|Tasa|0.160000'),
                    retenciones=[cfdi33.Impuesto.parse('001|Tasa|0.100000'), cfdi33.Impuesto.parse('002|Tasa|0.106667')],
                )
            )
        ]
    )

    with mock.patch(f'requests.request') as mk:
        mk.return_value.json = mock.Mock(return_value={
            "uuid": "3d94d0c5-9d4d-4c73-a61b-d083c553b7cc",
            "content": "dGhpcyBpcyBhIHRlc3QgeG1s"
        })
        diverza.stamp(cfdi=cfdi)

        assert mk.called
        mk.call_args.kwargs["headers"]["User-Agent"] = 'this is a test'

        args = json.dumps(mk.call_args.kwargs, indent=2)
        verify = verify_result(data=args, filename="test_diverza_stamp.json")
        assert verify

    with mock.patch(f'requests.request') as mk:
        mk.return_value.json = mock.Mock(return_value={
            "uuid": "3d94d0c5-9d4d-4c73-a61b-d083c553b7cc",
            "content": "dGhpcyBpcyBhIHRlc3QgeG1s"
        })
        diverza.issue(
            cfdi=cfdi,
            # certificate_number=signer.certificate_number()
        )

        assert mk.called
        mk.call_args.kwargs["headers"]["User-Agent"] = 'this is a test'

        args = json.dumps(mk.call_args.kwargs, indent=2)
        verify = verify_result(data=args, filename="test_diverza_issue.json")
        assert verify


def test_diverza_stamp_v40():
    signer = get_signer('xiqb891116qe4')
    emisor = Issuer(signer=signer, tax_system="601")

    diverza = Diverza(
        rfc="AAA010101AAA",
        id="3935",
        token="ABCD1234",
        environment=Environment.TEST
    )

    cfdi = cfdi40.Comprobante(
        emisor=emisor,
        lugar_expedicion="56820",
        fecha=datetime.fromisoformat("2022-09-28T22:40:38"),
        receptor=cfdi40.Receptor(
            rfc='KIJ0906199R1',
            nombre='KIJ, S.A DE C.V.',
            uso_cfdi='G03',
            domicilio_fiscal_receptor="59820",
            regimen_fiscal_receptor="601"
        ),
        metodo_pago='PPD',
        serie="A",
        folio="123456",
        conceptos=[
            cfdi40.Concepto(
                cuenta_predial='1234567890',
                clave_prod_serv='10101702',
                cantidad=Decimal('1.00'),
                clave_unidad='E48',
                descripcion='SERVICIOS DE FACTURACION',
                valor_unitario=Decimal('15390.30'),
                impuestos=cfdi40.Impuestos(
                    traslados=cfdi40.Impuesto.parse('002|Tasa|0.160000'),
                    retenciones=[cfdi40.Impuesto.parse('001|Tasa|0.100000'), cfdi40.Impuesto.parse('002|Tasa|0.106667')],
                )
            )
        ]
    )

    with mock.patch(f'requests.request') as mk:
        mk.return_value.json = mock.Mock(return_value={
            "uuid": "3d94d0c5-9d4d-4c73-a61b-d083c553b7cc",
            "content": "dGhpcyBpcyBhIHRlc3QgeG1s"
        })
        diverza.stamp(cfdi=cfdi)

        assert mk.called
        mk.call_args.kwargs["headers"]["User-Agent"] = 'this is a test'

        args = json.dumps(mk.call_args.kwargs, indent=2)
        verify = verify_result(data=args, filename="test_diverza_stamp_v40.json")
        assert verify

    with mock.patch(f'requests.request') as mk:
        mk.return_value.json = mock.Mock(return_value={
            "uuid": "3d94d0c5-9d4d-4c73-a61b-d083c553b7cc",
            "content": "dGhpcyBpcyBhIHRlc3QgeG1s"
        })
        diverza.issue(
            cfdi=cfdi,
            # certificate_number=signer.certificate_number()
        )

        assert mk.called
        mk.call_args.kwargs["headers"]["User-Agent"] = 'this is a test'

        args = json.dumps(mk.call_args.kwargs, indent=2)
        verify = verify_result(data=args, filename="test_diverza_issue_v40.json")
        assert verify


def test_diverza_stamp_pago_v40():
    signer = get_signer('xiqb891116qe4')
    emisor = Issuer(signer=signer, tax_system="601")

    diverza = Diverza(
        rfc="AAA010101AAA",
        id="3935",
        token="ABCD1234",
        environment=Environment.TEST
    )

    cfdi = cfdi40.Comprobante.pago(
        emisor=emisor,
        fecha=datetime.fromisoformat("2022-09-28T22:40:38"),
        receptor=cfdi40.Receptor(
            rfc='KIJ0906199R1',
            nombre='KIJ, S.A DE C.V.',
            uso_cfdi='G03',
            domicilio_fiscal_receptor="59820",
            regimen_fiscal_receptor="601"
        ),
        lugar_expedicion="56820",
        complemento_pago=pago20.Pagos(
            pago=pago20.Pago(
                fecha_pago=datetime(2020, 1, 1),
                forma_de_pago_p='03',
                moneda_p='MXN',
                tipo_cambio_p=1,
                docto_relacionado=pago20.DoctoRelacionado(
                    id_documento='d6042dc8-d525-4e78-8d1b-092c878bd518',
                    imp_pagado=Decimal("100.3"),
                    imp_saldo_ant=Decimal("203.45"),
                    num_parcialidad=3,
                    moneda_dr="MXN",
                    objeto_imp_dr="01"
                )
            )
        ),
        serie="A",
        folio="123456"
    )

    with mock.patch(f'requests.request') as mk:
        mk.return_value.json = mock.Mock(return_value={
            "uuid": "3d94d0c5-9d4d-4c73-a61b-d083c553b7cc",
            "content": "dGhpcyBpcyBhIHRlc3QgeG1s"
        })
        diverza.stamp(cfdi=cfdi)

        assert mk.called
        mk.call_args.kwargs["headers"]["User-Agent"] = 'this is a test'

        args = json.dumps(mk.call_args.kwargs, indent=2)
        verify = verify_result(data=args, filename="test_diverza_stamp_pago_v40.json")
        assert verify

    with mock.patch(f'requests.request') as mk:
        mk.return_value.json = mock.Mock(return_value={
            "uuid": "3d94d0c5-9d4d-4c73-a61b-d083c553b7cc",
            "content": "dGhpcyBpcyBhIHRlc3QgeG1s"
        })
        diverza.issue(
            cfdi=cfdi,
            # certificate_number=signer.certificate_number()
        )

        assert mk.called
        mk.call_args.kwargs["headers"]["User-Agent"] = 'this is a test'

        args = json.dumps(mk.call_args.kwargs, indent=2)
        verify = verify_result(data=args, filename="test_diverza_issue_pago_v40.json")
        assert verify

