# Crea o modifica usuarios en sportaccess
import requests
import json
from .init_creds import init_mongo, test
from datetime import datetime
from .projections import proj_accesso_cliente
from pymongo import ReturnDocument
from .format import datetime_parser, fix_bad_characters
from muvinai.utilities.dates import localize

db = init_mongo()

zonas = {
    "Elite": "-1",
    "Total": "1",
    "Plus": "2",
    "Local": "7"
}

sedes = {
    "CORP": "1",
    "ECOM": "900",
    "ALIA": "901",
    "WORK": "1010",
    "MUVI": "900"
}

all_clubes = db.club.find({"sportaccess_id": {"$exists": True}})


# sede_map = {c["sportaccess_id"]: c["name"] for c in all_clubes}
# additional_map = {
#    1: "Corporate",
#    900: "e-Commerce",
#    901: "Alianzas"
# }
# sede_map.update(additional_map)


def crear_usuario_sportclub(cliente: dict, payment_id: int = -1, nivel_de_acceso: str = 'buscar_plan') -> dict:
    """ Crear un usuario en la base de datos de Sportclub

    :param cliente: cliente de mongodb
    :type cliente: dict
    :param payment_id: id del pago de mercadopago
    :type payment_id: str
    :param nivel_de_acceso: nivel de acceso del plan
    :type nivel_de_acceso: str
    :return: los valores posibles son: Elite, Total, Plus, Local, Flex
    :rtype: dict
    """
    db = init_mongo()
    url = "https://apisami.sportclubaccess.com/2.0/socio?"

    plan = db.planes.find_one({"_id": cliente["active_plan_id"]})
    if nivel_de_acceso == 'buscar_plan':
        try:
            nivel_de_acceso = plan['nivel_de_acceso']
        except:
            nivel_de_acceso = 'Total'
    try:
        if plan["sede_local"] is None:
            sede_value = sedes[cliente["sportaccess_id"][0:4]]
        else:
            club = db.club.find_one({"_id": plan["sede_local"]})
            sede_value = club["sportaccess_id"]
    except:
        sede_value = "1"

    if payment_id == -1:
        try:
            payment_id = cliente['payment_ids'][-1]
        except:
            payment_id = 11

    for a in cliente["domicilio"]:
        if not a:
            cliente["domicilio"][a] = "n/a"

    if "nacimiento" not in cliente.keys():
        cliente["nacimiento"] = "22/02/2022"
    elif not cliente["nacimiento"] or cliente["nacimiento"] == "n/a":
        cliente["nacimiento"] = "22/02/2022"

    if "celular" not in cliente.keys():
        cliente["celular"] = "n/a"
    elif not cliente["celular"]:
        cliente["celular"] = "n/a"

    parameters = {
        "username": "3rdPty2902-8891-20",
        "password": "HWXSroa76FSI226JeEtOd9SqDoDXCkGtJyXTk2qEAN2HI34bOVe",
        "nro_socio": cliente["sportaccess_id"],
        "nombre": cliente["nombre"],
        "apellido": cliente["apellido"],
        "documento": cliente["documento"],
        "email": cliente["email"],
        "sexo": "X",
        "nacimiento": cliente["nacimiento"].replace("/", "-"),
        "celular": cliente["celular"],
        "calle": cliente["domicilio"]["calle"],
        "numero": cliente["domicilio"]["altura"],
        "localidad": cliente["domicilio"]["localidad"],
        "cp": cliente["domicilio"]["código postal"],
        "ciudad": cliente["domicilio"]["localidad"],
        "provincia": cliente["domicilio"]["provincia"],
        "nacionalidad": "Argentino",
        "sede": sede_value,
        "zona": "7" if nivel_de_acceso == "Flex" else zonas[nivel_de_acceso],
        "mp_payment_id": int(payment_id),
        "vigencia": cliente["fecha_vigencia"].strftime("%d-%m-%Y")

    }

    lista = [key + "=" + str(parameters[key]) for key in parameters.keys()]
    querystrings = "&".join(lista)
    if test:
        print("Se saltea el post a sportaccess por ser test.")
        return {"status": True, "message": "No se llamó al servicio por ser TEST."}
    r = requests.post(url + querystrings)
    response = r.json()
    if not response["status"]:
        print("Falló la creación de usuario en bd sporclub")
        print(response["message"])
    else:
        print("Usuario creado satisfactoriamente en bd sportclub")

    return response


def consulta_socio(documento: str) -> dict:
    """ Obtener un socio de la base de datos de sportclub
great
    :param documento: numero de documento del socio que buscado
    :type documento: str
    :return: respuesta de SpAccess (puede ser un socio o un mensaje de error)
    :rtype: dict
    """
    url = "https://apisami.sportclubaccess.com/2.0/members?Documento="
    r = requests.get(url + documento)
    r = r.json()
    try:  # Intento corregir los malos caracteres que puedan tener
        r['data']['Apellido'] = fix_bad_characters(r['data']['Apellido'])
        r['data']['Nombre'] = fix_bad_characters(r['data']['Nombre'])
        r['data']['Direccion'] = fix_bad_characters(r['data']['Direccion'])
    except:
        pass
    # Intenta pasar a datetime la fecha
    try:
        r['data']['Vigencia'] = datetime.strptime(r['data']['Vigencia'], '%d/%m/%Y')
        r['data']["FechaIngreso"] = datetime.strptime(r['data']["FechaIngreso"], '%d/%m/%Y')
    except:
        pass
    # Intenta convertir el apto medico
    try:
        r['data']['AptoMedico'] = datetime.strptime(r['data']['AptoMedico'], '%d/%m/%Y')
    except:
        pass
    return r


def consulta_socio_x_nro_socio(nro_socio: str) -> dict:
    """ Obtener un socio de la base de datos de sportclub

    :param documento: numero de documento del socio que buscado
    :type documento: str
    :return: respuesta de SpAccess (puede ser un socio o un mensaje de error)
    :rtype: dict
    """
    url = "https://apisami.sportclubaccess.com/2.0/members?NroSocio="
    r = requests.get(url + nro_socio)
    r = r.json()
    try:  # Intento corregir los malos caracteres que puedan tener
        r['data']['Apellido'] = fix_bad_characters(r['data']['Apellido'])
        r['data']['Nombre'] = fix_bad_characters(r['data']['Nombre'])
        r['data']['Direccion'] = fix_bad_characters(r['data']['Direccion'])
    except:
        pass
    try:  # Intenta pasar a datetime la fecha
        r['data']['Vigencia'] = datetime.strptime(r['data']['Vigencia'], '%d/%m/%Y')
        r['data']["FechaIngreso"] = datetime.strptime(r['data']["FechaIngreso"], '%d/%m/%Y')
    except:
        pass
    # Intenta convertir el apto medico
    try:
        r['data']['AptoMedico'] = datetime.strptime(r['data']['AptoMedico'], '%d/%m/%Y')
    except:
        pass
    return r


def create_external_user(data: dict) -> dict:
    """ Crear un cliente externo en mongodb

    :param data: datos del socio (estos datos se obtienen de la base de sportclub)
    :type data: dict
    :return: datos del socio con los que se guardo en mongodb
    :rtype: dict
    """

    inv_zonas = {a: b for b, a in zonas.items()}
    na = "Elite" if data["Documento"] in strelites else inv_zonas[str(data["Zona"])]

    nuevo_socio = {
        "sportaccess_id": data["NroSocio"],
        "nivel_de_acceso": na,
        "nombre": data["Nombre"],
        "apellido": data["Apellido"],
        "documento": data["Documento"],
        "email": data["Mail"],
        "domicilio": {
            "calle": data["Direccion"],
            "altura": data["Numero"],
            "apto_lote": data["Piso"],
            "localidad": data["Localidad"],
            "provincia": data["Provincia"],
            "código postal": data["CPostal"]
        },
        "celular": data["Movil"],
        "status": "externo",
        "fecha_vigencia": data["Vigencia"],
        "nacimiento": data["Nacimiento"],
        "last_subscription_date": data["FechaIngreso"],
        "sede": data["Sede"],
        "sede_sqlid": int(data["Sede-SqlId"]),
        "plan": data["Plan"],
        "active_plan_id": None,
        "apto_medico_externo": data["AptoMedico"],
        "brand_name": 'SportClub'
    }
    socio = db.clientes.update_one({"documento": data["Documento"], "sportaccess_id": {"$exists": True}},
                                   {"$set": nuevo_socio}, upsert=True)
    nuevo_socio["_id"] = socio.upserted_id
    return nuevo_socio


def cambio_de_plan(documento: str):
    """ Actualizar en mongodb y en SpAccess el plan del socio

    :param documento: numero de documento del socio al cual se le quiere cambiar el plan
    :type documento: str
    """
    db = init_mongo()
    cliente = db.clientes.find_one({"documento": documento})
    cliente["active_plan"] = "total-mensual"
    cliente["nivel_de_acceso"] = "Total"
    crear_usuario_sportclub(cliente, cliente["last_payment_id"], cliente["nivel_de_acceso"])
    db.clientes.update_one({"documento": documento}, {"$set": cliente})


def update_external_user(data: dict):
    """ Actualizar cliente externo

    :param data: datos que se van a actualizar (tienen que estar las keys: Documento, \
                    Zona, NroSocio, Nombre, Apellido, Documento, Mail, Direccion, Numero, Piso, Localidad,\
                    Provincia, CPostal, Movil, Vigencia, Nacimiento, FechaIngreso)
    :type data: dict
    """
    inv_zonas = {a: b for b, a in zonas.items()}
    na = "Elite" if data["Documento"] in strelites else inv_zonas[str(data["Zona"])]

    socio = {
        "sportaccess_id": data["NroSocio"],
        "nivel_de_acceso": na,
        "nombre": data["Nombre"],
        "apellido": data["Apellido"],
        "documento": data["Documento"],
        "email": data["Mail"],
        "domicilio": {
            "calle": data["Direccion"],
            "altura": data["Numero"],
            "apto_lote": data["Piso"],
            "localidad": data["Localidad"],
            "provincia": data["Provincia"],
            "código postal": data["CPostal"]
        },
        "celular": data["Movil"],
        "status": "externo",
        "fecha_vigencia": data["Vigencia"],
        "nacimiento": data["Nacimiento"],
        "last_subscription_date": data["FechaIngreso"],
        "sede": data["Sede"],
        "sede_sqlid": int(data["Sede-SqlId"]),
        "plan": data["Plan"],
        "active_plan_id": None,
        "apto_medico_externo": data["AptoMedico"],
        "brand_name": 'SportClub'
    }
    return db.clientes.find_one_and_update({"documento": data["Documento"]}, {"$set": socio},
                                           return_document=ReturnDocument.AFTER)


def resolve_external_status(documento):
    _client = db.clientes.find_one({"documento": documento, "email": {"$not": {"$regex": "@migracion"}}})
    if not _client or _client["status"] == "inactivo":
        r = consulta_socio(documento)
        try:
            if r["code"] == 404:
                return "*El DNI ingresado no se encuentra en nuestros registros. " \
                       "Por favor ingresá un DNI válido para continuar."
            elif r["code"] > 299:
                return r["message"]
            else:
                return create_external_user(r["data"])
        except:
            return "El servicio de SportAccess no retorna información válida para este documento."
    elif _client["status"] == "externo":
        r = consulta_socio(documento)
        return update_external_user(r["data"])
    else:
        return _client


def consulta_socio_proclub(documento: str) -> dict:
    """ Obtener un socio de la base de datos de sportclub
great
    :param documento: numero de documento del socio que buscado
    :type documento: str
    :return: respuesta de SpAccess (puede ser un socio o un mensaje de error)
    :rtype: dict
    """
    url = "https://apisocios.sportclub.com.ar:3000/members?Documento="
    headers = {
        "x-api-key": "VHGFDn_2212FFF**/-FFFF",
        "Content-Type": "application/json"
    }
    r = requests.get(url + documento, headers=headers)
    r = r.json()

    try:
        int(r["code"])
    except ValueError:
        return
    if r["code"] >= 400:
        return
    if not r["data"]:
        return

    proclub = r["data"][0]
    if "CredencialSpice" in proclub.keys():
        spice = proclub["CredencialSpice"]
    else:
        spice = None

    # Intentamos conversión a formato perfilsocio
    socio = {"_id": None,
             "fecha_vigencia": localize(datetime.strptime(proclub['Vigencia'], '%d/%m/%Y')),
             "last_subscription_date": localize(datetime.strptime(proclub["FechaIngreso"], '%d/%m/%Y')),
             "apto_medico": {"fecha_vigencia": localize(datetime.strptime(proclub['AptoMedico'], '%d/%m/%Y'))},
             "apellido": proclub["Apellido"],
             "documento": documento,
             "nombre": proclub["Nombre"],
             "plan_details": {
                 "nivel_de_acceso": proclub["nivel_acceso"].lower(),
                 "name": proclub["Plan"],
                 "merchant_id": None,
                 "sede_local": proclub["Sede"]
             },
             "token_spice": spice,
             "seller_merchant": None,
             "externo": True,
             "sede_sqlid": proclub["Sede-SqlId"],
             "proclub_id": proclub["NroSocio"]
             }

    return socio


def update_spice(nro_socio: str, spice) -> dict:
    """ Obtener un socio de la base de datos de sportclub
great
    :param documento: numero de documento del socio que buscado
    :type documento: str
    :return: respuesta de SpAccess (puede ser un socio o un mensaje de error)
    :rtype: dict
    """
    url = "https://apisocios.sportclub.com.ar:3000/members?NroSocio="
    headers = {
        "x-api-key": "VHGFDn_2212FFF**/-FFFF",
        "Content-Type": "application/json"
    }
    body = {"Credencial_spice": spice}
    r = requests.put(url + nro_socio, headers=headers, data=json.dumps(body))
    return r