import pytest
from django.contrib.contenttypes.models import ContentType
from httmock import HTTMock

from passerelle.base.models import AccessRight, ApiUser
from passerelle.contrib.grandlyon_streetsections.models import (
    GrandLyonStreetSections,
    StreetSection,
    normalize_street,
)


@pytest.fixture()
def connector(db):
    api = ApiUser.objects.create(username='all', keytype='', key='')
    connector = GrandLyonStreetSections.objects.create(slug='gl-streetsections')
    obj_type = ContentType.objects.get_for_model(connector)
    AccessRight.objects.create(
        codename='can_access', apiuser=api, resource_type=obj_type, resource_pk=connector.pk
    )
    return connector


def test_partial_bornes(app, connector):
    name = "Rue d'Essling"
    normalized_name = normalize_street(name)
    codefuv = '27862'
    codeinsee = '69383'
    nomcommune = 'LYON 3'
    StreetSection.objects.create(
        nom=normalized_name,
        nomcommune=nomcommune,
        codefuv=codefuv,
        codeinsee=codeinsee,
        codetroncon='T3162',
        bornemingauche=0,
        bornemaxgauche=99999,
        bornemindroite=14,
        bornemaxdroite=14,
    )
    StreetSection.objects.create(
        nom=normalized_name,
        nomcommune=nomcommune,
        codefuv=codefuv,
        codeinsee=codeinsee,
        codetroncon='T27587',
        bornemingauche=0,
        bornemaxgauche=99999,
        bornemindroite=0,
        bornemaxdroite=99999,
    )
    StreetSection.objects.create(
        nom=normalized_name,
        nomcommune=nomcommune,
        codefuv=codefuv,
        codeinsee=codeinsee,
        codetroncon='T3165',
        bornemingauche=19,
        bornemaxgauche=21,
        bornemindroite=16,
        bornemaxdroite=26,
    )

    response = app.get(
        "/grandlyon-streetsections/gl-streetsections/section_info"
        "?streetname=Rue d'Essling&commune=Lyon&streetnumber=20"
    )
    assert response.json['err'] == 0
    assert response.json['data']['codetroncon'] == 'T3165'


DATA_EXAMPLE = """{
   "fields" : [
      "nom",
      "nomcommune",
      "codeinsee",
      "codefuv",
      "codetroncon",
      "importance",
      "domanialite",
      "typecirculation",
      "senscirculation",
      "senscircspecialise",
      "bornemingauche",
      "bornemaxgauche",
      "bornemindroite",
      "bornemaxdroite",
      "datecreation",
      "datemajalpha",
      "datemajgraph",
      "datemajborne",
      "observation",
      "datedomanialite",
      "referencedomanialite",
      "particularite",
      "gestionnaire",
      "denomroutiere",
      "gid"
   ],
   "layer_name" : "adr_voie_lieu.adraxevoie",
   "nb_results" : 4,
   "next" : "https://download.recette.data.grandlyon.com/ws/grandlyon/adr_voie_lieu.adraxevoie/all.json?compact=false&start=5&maxfeatures=4",
   "table_href" : "https://download.recette.data.grandlyon.com/ws/grandlyon/adr_voie_lieu.adraxevoie.json",
   "values" : [
      {
         "bornemaxdroite" : null,
         "bornemaxgauche" : null,
         "bornemindroite" : null,
         "bornemingauche" : null,
         "codefuv" : "30906",
         "codeinsee" : "69233",
         "codetroncon" : "T5869",
         "datecreation" : "1996-01-01",
         "datedomanialite" : null,
         "datemajalpha" : "1996-01-01",
         "datemajborne" : "1996-01-01",
         "datemajgraph" : "2015-06-16",
         "denomroutiere" : null,
         "domanialite" : "Commune",
         "gestionnaire" : "",
         "gid" : 1,
         "importance" : "petite rue",
         "nom" : "Chemin Rural 10",
         "nomcommune" : "ST-ROMAIN",
         "observation" : null,
         "particularite" : null,
         "referencedomanialite" : null,
         "senscircspecialise" : null,
         "senscirculation" : "Double",
         "typecirculation" : "autres"
      },
      {
         "bornemaxdroite" : null,
         "bornemaxgauche" : null,
         "bornemindroite" : null,
         "bornemingauche" : null,
         "codefuv" : "31631",
         "codeinsee" : "69276",
         "codetroncon" : "T15908",
         "datecreation" : "1996-01-01",
         "datedomanialite" : null,
         "datemajalpha" : "1996-01-01",
         "datemajborne" : "2002-09-27",
         "datemajgraph" : "2014-12-11",
         "denomroutiere" : null,
         "domanialite" : "Métropole",
         "gestionnaire" : "",
         "gid" : 2,
         "importance" : "petite rue",
         "nom" : "Rue des Charrières",
         "nomcommune" : "FEYZIN",
         "observation" : null,
         "particularite" : null,
         "referencedomanialite" : null,
         "senscircspecialise" : null,
         "senscirculation" : "Double",
         "typecirculation" : "générale"
      },
      {
         "bornemaxdroite" : 6,
         "bornemaxgauche" : 15,
         "bornemindroite" : 2,
         "bornemingauche" : 1,
         "codefuv" : "24089",
         "codeinsee" : "69282",
         "codetroncon" : "T13986",
         "datecreation" : "1996-01-01",
         "datedomanialite" : null,
         "datemajalpha" : "1996-01-01",
         "datemajborne" : "2013-08-01",
         "datemajgraph" : "2015-10-01",
         "denomroutiere" : null,
         "domanialite" : "Privé",
         "gestionnaire" : "",
         "gid" : 3,
         "importance" : "moyenne rue",
         "nom" : "Rue Alfred de Vigny",
         "nomcommune" : "MEYZIEU",
         "observation" : null,
         "particularite" : null,
         "referencedomanialite" : null,
         "senscircspecialise" : null,
         "senscirculation" : "Double",
         "typecirculation" : "générale"
      },
      {
         "bornemaxdroite" : 10,
         "bornemaxgauche" : null,
         "bornemindroite" : 2,
         "bornemingauche" : null,
         "codefuv" : "22503",
         "codeinsee" : "69273",
         "codetroncon" : "T9865",
         "datecreation" : "1996-01-01",
         "datedomanialite" : "2015-11-24",
         "datemajalpha" : "2015-11-24",
         "datemajborne" : "2005-12-09",
         "datemajgraph" : "2019-12-20",
         "denomroutiere" : null,
         "domanialite" : "Privé",
         "gestionnaire" : "",
         "gid" : 4,
         "importance" : "moyenne place",
         "nom" : "Place Jules Ferry",
         "nomcommune" : "CORBAS",
         "observation" : null,
         "particularite" : null,
         "referencedomanialite" : null,
         "senscircspecialise" : null,
         "senscirculation" : "Double",
         "typecirculation" : "générale"
      },
      {
         "bornemaxdroite" : 10,
         "bornemaxgauche" : 11,
         "bornemindroite" : 2,
         "bornemingauche" : 1,
         "codefuv" : "21424",
         "codeinsee" : "69266",
         "codetroncon" : "T54753",
         "datecreation" : "1995-07-17 18:43:00+02:00",
         "datedomanialite" : null,
         "datemajalpha" : "2022-11-14",
         "datemajborne" : "2022-07-26",
         "datemajgraph" : "2022-07-26",
         "denomroutiere" : null,
         "domanialite" : "Métropole",
         "gestionnaire" : null,
         "gid" : 30067,
         "importance" : "Petite rue",
         "nom" : "Rue de l'Avenir",
         "nomcommune" : "Villeurbanne",
         "observation" : null,
         "particularite" : null,
         "referencedomanialite" : null,
         "senscircspecialise" : null,
         "senscirculation" : "Inverse",
         "typecirculation" : "Générale"
      }
   ]
}
"""


def data_mock(url, request):
    return {'content': DATA_EXAMPLE, 'request': request, 'status_code': 200}


def old_data_mock(url, request):
    # old data.grandlyon used string "None" for null values
    return {'content': DATA_EXAMPLE.replace(': null', ': "None"'), 'request': request, 'status_code': 200}


def test_daily_none_bornes(app, connector):
    StreetSection.objects.all().delete()
    with HTTMock(data_mock):
        connector.daily()
        assert StreetSection.objects.get(codetroncon='T5869').bornemindroite == 0
        assert StreetSection.objects.get(codetroncon='T5869').bornemaxdroite == 99999
        assert StreetSection.objects.get(codetroncon='T9865').bornemindroite == 2
        assert StreetSection.objects.get(codetroncon='T9865').bornemaxdroite == 10

    StreetSection.objects.all().delete()
    with HTTMock(old_data_mock):
        connector.daily()
        assert StreetSection.objects.get(codetroncon='T5869').bornemindroite == 0
        assert StreetSection.objects.get(codetroncon='T5869').bornemaxdroite == 99999


def test_non_uppercase_communes(app, connector):
    StreetSection.objects.all().delete()
    with HTTMock(data_mock):
        connector.daily()
        response = app.get(
            "/grandlyon-streetsections/gl-streetsections/section_info"
            "?streetname=Rue de l'Avenir&commune=Villeurbanne&streetnumber=8"
        )
        assert response.json['err'] == 0
        assert response.json['data']['codetroncon'] == 'T54753'
