from datetime import datetime
from enum import Enum

from Facturacion.models import tipoServicio, DetalleOrden
from TransitoApp.settings import BASE_DIR
from sri.models import Configuracion
import os
import subprocess

import dicttoxml as dicttoxml
from xml.dom.minidom import parseString
import zeep

class Ambientes(Enum):
    PRUEBAS_AUTH='https://celcer.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl'
    PRUEBAS_CONSULT='https://celcer.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl'
    PRODUCCION_AUTH='https://cel.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl'
    PRODUCCION_CONSULT='https://cel.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl'



def modulo_11(fecha: str, ruc: str, ambiente: str, establecimiento: str, puntoEmision: str, secuencial: str):
    union = fecha + '01' + ruc + ambiente + establecimiento + puntoEmision + secuencial + '10000000' + '1'
    print(union)
    lista = [i for i in union]
    n = len(lista)
    print("Cantidad: ", n)
    digito = 0
    pibot = 2
    for i in range(n):
        n = n - 1
        digito += int(lista[n]) * pibot
        pibot = pibot + 1
        if pibot > 7:
            pibot = 2
    digito = 11 - (digito % 11)
    if digito == 10:
        digito = 1
    elif digito == 11:
        digito = 0
    union = union + str(digito)
    print("tamaño de la clave de acceso: ", len(union))
    return union


def firmar(ruta,clave):
    ruta_p12 = os.path.join(BASE_DIR,'static','facturacion','0702864901.p12')
    print("Ruta de la firma:",ruta_p12)
    clave_p12 = 'transito2024'
    ruta_xml_entrada = ruta
    ruta_salida = os.path.join(BASE_DIR,'media','facturacion','firmado')
    archivo_salida = f'{clave}' + '.xml'
    ruta_jar =  os.path.join(BASE_DIR, 'sri','comprobantes.jar')
    # cmd_ej = f'java -jar {ruta_jar} {ruta_xml_entrada} {ruta_p12} {clave_p12} {ruta_salida} {archivo_salida}'
    params=[ruta_xml_entrada,ruta_p12,clave_p12,ruta_salida,archivo_salida]
    print(['/usr/bin/java','-jar',{ruta_jar}]+list(params))
    subprocess.call(['/usr/bin/java','-jar','/var/www/html/TransitoApp/sri/comprobantes.jar']+list(params))
    print('firmado..!!')
    return os.path.join(BASE_DIR,'media','facturacion','firmado',archivo_salida)

def enviar_sri(documento:str):
    configuracion = Configuracion.objects.get(estado=True)
    url=""
    if configuracion.ambiente=='1':
        print('Ambiente de pruebas')
        url=Ambientes.PRUEBAS_AUTH.value #ruta al servidor de pruebas
    else:
        print('Ambiente de produccion')
        url=Ambientes.PRODUCCION_AUTH.value
    archivo=os.path.join(BASE_DIR,'media','firmado',documento)
    comprobante=open(archivo, "rb") #apertura del archivo xml
    xmlBytes = comprobante.read()# creando mapa de bits del comprobante
    client = zeep.Client(wsdl=url)#creando una instancia de zeep cliente
    print("Inicia el proceso de envio..!!")
    result=client.service.validarComprobante(xmlBytes)
    print(result)
    print("Finaliza el envio..!")
    ar=os.path.join(BASE_DIR,'media','respuesta',documento)
    jsonarchivo=open(documento+'.json',"w",encoding='utf-8')
    jsonarchivo.write(str(result))
    jsonarchivo.close()

def consultar_envio(documento):
    configuracion = Configuracion.objects.get(estado=True)
    url=""
    print(Ambientes.PRUEBAS_CONSULT.value)
    if configuracion.ambiente=="1":
        url = Ambientes.PRUEBAS_CONSULT.value
    else:
        url = Ambientes.PRODUCCION_CONSULT.value
    client = zeep.Client(wsdl=url)
    respuesta=client.service.autorizacionComprobante(documento)
    print(respuesta)
    #loc=os.path.join(BASE_DIR,'media','facturacion','respuestas',documento)
    loc='/var/www/html/TransitoApp/media/facturacion/respuesta/'+documento+'.json'
    jsonarchivo = open(loc, "w",encoding='utf-8')
    jsonarchivo.write(str(respuesta))
    jsonarchivo.close()
    try:
        return respuesta['autorizaciones']['autorizacion'][0]['estado']
    except:
        return "NO AUTORIZADO"

def generar_xml(orden, detalle):
    configuracion = Configuracion.objects.get(estado=True)
    tipo_servicio = tipoServicio.objects.get(descripcion='Servicios administrativos', estado=True)
    fecha = orden.fecha.date().strftime("%d%m%Y")
    fecha2 = orden.fecha.date().strftime("%d/%m/%Y")
    detalle.emision=datetime.now().date()

    detx=DetalleOrden.objects.extra(where=["CHAR_LENGTH(n_comprobante) >= 8"]).count()

    contador=detx+Configuracion.objects.get(estado=True).secuencial
    print('contador',detx, 'valor',contador)
    if not detalle.n_comprobante:
        detalle.n_comprobante=str.zfill(str(contador),9)
        detalle.save()
    print("Número del comprobante",detalle.n_comprobante)
    documento = modulo_11(fecha, configuracion.ruc, configuracion.ambiente, configuracion.establecimiento, configuracion.ptoEmision,
                          detalle.n_comprobante)
    infoTributaria = {
        'ambiente': configuracion.ambiente,
        'tipoEmision': 1,
        'razonSocial': configuracion.razon_social,
        'ruc': configuracion.ruc,
        'claveAcceso': documento,
        'codDoc': '01',
        'estab': configuracion.establecimiento,
        'ptoEmi': detalle.punto_emision,
        'secuencial': detalle.n_comprobante,
        'dirMatriz': configuracion.direccion,
        'contribuyenteRimpe': 'CONTRIBUYENTE RÉGIMEN RIMPE'
    }
    infoFactura = {
        'fechaEmision': fecha2,
        'dirEstablecimiento': configuracion.direccion,
        'obligadoContabilidad': 'SI',
        'tipoIdentificacionComprador': orden.cliente.identificacion,
        'razonSocialComprador': orden.cliente.razon_social,
        'identificacionComprador': orden.cliente.numero_identificacion,
        'direccionComprador': orden.cliente.direccion,
        'totalSinImpuestos': float(detalle.costo)+ float(tipo_servicio.costo),
        'totalDescuento': '0.00',
        'totalConImpuestos': {
            'totalImpuesto': {
                'codigo': 2,
                'codigoPorcentaje': 6,
                'baseImponible': float(detalle.costo)+ float(tipo_servicio.costo),
                'valor': 0.00,
            }
        },
        'propina': 0,
        'importeTotal': float(detalle.costo)+ float(tipo_servicio.costo),
        'moneda': 'DOLAR',
        'pagos': {
            'pago': {
                'formaPago': 20,
                'total': float(detalle.costo) + float(tipo_servicio.costo),
            }
        }
    }
    detalles = {
        'detalle': {
            'codigoPrincipal': f'RCD-{str.zfill(str(detalle.items.id), 3)}',
            'descripcion': detalle.items.descripcion,
            'cantidad': detalle.cantidad,
            'precioUnitario': detalle.costo,
            'descuento': 0,
            'precioTotalSinImpuesto': float(detalle.costo)*float(detalle.cantidad),
            'impuestos': {
                'impuesto': {
                    'codigo': 2,
                    'codigoPorcentaje': 6,
                    'tarifa': 0.0,
                    'baseImponible': float(detalle.costo)*float(detalle.cantidad),
                    'valor': 0
                }
            }
        },
        '_detalle': {
            'codigoPrincipal': f'RCD-{str.zfill(str(tipo_servicio.id), 3)}',
            'descripcion': tipo_servicio.descripcion,
            'cantidad': 1,
            'precioUnitario': tipo_servicio.costo,
            'descuento': 0,
            'precioTotalSinImpuesto': tipo_servicio.costo,
            'impuestos': {
                'impuesto': {
                    'codigo': 2,
                    'codigoPorcentaje': 6,
                    'tarifa': 0.0,
                    'baseImponible': tipo_servicio.costo,
                    'valor': 0
                }
            }
        }
    }
    infoAdicional = {
        '@Teléfono': orden.cliente.telefono,
        '@Email': orden.cliente.email,
        '@Concepto': f'{str.upper(detalle.items.descripcion)} DEL VEHICULO DE PLACAS {str.upper(orden.placa)}',
        '@No. Orden': orden.numero
    }
    data = {
        'factura': {
            'infoTributaria': infoTributaria,
            'infoFactura': infoFactura,
            'detalles': detalles,
            'infoAdicional': infoAdicional
        }
    }

    detalle.numero_autorizacion=documento
    ruta_xml = str(os.path.abspath(
        os.path.join(BASE_DIR, 'media', 'facturacion', 'xml', f'{documento}.xml')))
    xml = dicttoxml.dicttoxml(data, root=False, ids=False, attr_type=False, encoding='utf-8')
    xml = parseString(xml).toprettyxml().replace('<factura>', '<factura id="comprobante" version="1.1.0">').replace('_detalle', 'detalle') \
        .replace('key', 'campoAdicional').replace('name', 'nombre').replace('@T', 'T').replace("@E", 'E') \
        .replace("@C", 'C').replace("@N", 'N')
    archivo = open(ruta_xml, 'w', encoding='utf-8')
    archivo.write(xml)
    archivo.close()
    ruta=firmar(ruta_xml,documento)
    enviar_sri(ruta)
    detalle.estado = consultar_envio(documento)
    detalle.save()
    return contador
