from unittest import mock
from unittest.mock import patch, ANY
from django.conf import settings
from django.http import QueryDict
from django.test import TestCase
from recuperateur_reseau_viaire.forms import Graph_viaire_ville_informationForm
from OSM_outils.OMSnx_enregistrement import OMSnx_enregistrement


class form_creation_Graph_viaire_ville_informationTestCase(TestCase):

    def test_creation_form_vide(self):
        """
        Ce teste créé un formulaire de création de Graph_viaire_ville_information vide et ne doit pas être valide
        """
        form = Graph_viaire_ville_informationForm()
        self.assertFalse(form.is_valid())

    @patch('OSM_outils.OMSnx_enregistrement.OMSnx_enregistrement.recuperer_graphe_viaire_ville')
    def test_creation_form_une_ville_non_existante(self, mock_recuperer_graphe_viaire_ville):
        """
        Ce test créé un formulaire de création de Graph_viaire_ville_information avec un nom de ville qui n'existe pas
        """
        entree_form = QueryDict('gvvi_nom=coooooommmmmmuuuuuunnnnnneeeeee')
        form = Graph_viaire_ville_informationForm(entree_form)
        mock_recuperer_graphe_viaire_ville.side_effect = ValueError("erreur : \"" + entree_form.get("gvvi_nom") + "\"")
        self.assertFalse(form.is_valid())
        self.assertTrue("ville non trouvée : " + entree_form.get("gvvi_nom") in form.errors["gvvi_nom"])

    def test_creation_form_une_ville_basic_fichier_existe_deja(self):
        """
        Ce test va voir si une ville avec un nom connu fonctionne. Ici, c'est le nom d'un fichier dans le dossier Data.
        """
        nom_ville = "Saint-Laurent-sur-Saône"
        entree_form = QueryDict('gvvi_nom='+nom_ville)
        form = Graph_viaire_ville_informationForm(entree_form)
        self.assertTrue(form.is_valid())

    @patch('OSM_outils.OMSnx_enregistrement.OMSnx_enregistrement.sauvegarde_graphique')
    @patch('OSM_outils.OMSnx_enregistrement.OMSnx_enregistrement.chemin_vers_fichier_ville')
    def test_creation_form_une_ville_basic(self, mock_chemin_vers_fichier_ville, mock_sauvegarde_graphique):
        """
        Ce test va voir si une ville avec un nom connu fonctionne.
        """
        nom_ville = "Vaudherland"
        mock_chemin_vers_fichier_ville.return_value = settings.BASE_DIR.__str__() + "/recuperateur_reseau_viaire/Tests/Data/Vaudherland.graphml"
        entree_form = QueryDict('gvvi_nom='+nom_ville)
        form = Graph_viaire_ville_informationForm(entree_form)
        self.assertTrue(form.is_valid())
        mock_sauvegarde_graphique.assert_called_once_with(ANY, nom_ville)

    @patch('OSM_outils.OMSnx_enregistrement.OMSnx_enregistrement.recuperer_graphe_viaire_ville')
    def test_creation_form_plusieurs_villes_une_ville_n_existe_pas(self, mock_recuperer_graphe_viaire_ville):
        """
        Ici, on test la création d'une ville composé de plusieurs communes dont l'une des communes n'existe pas.
        """
        nom_ville = "super ville"
        nom_ville_englobees = ["Bolbec", "coooooommmmmmuuuuuunnnnnneeeeee"]
        entree_form = QueryDict("gvvi_nom=" + nom_ville + "&gvvi_nom_ajout=" + nom_ville_englobees[0] + "&gvvi_nom_ajout=" + nom_ville_englobees[1])
        mock_recuperer_graphe_viaire_ville.side_effect = ValueError("erreur : \"" + nom_ville_englobees[1] + "\"")
        form = Graph_viaire_ville_informationForm(entree_form)
        form.is_valid()
        self.assertTrue("ville non trouvée : " + nom_ville_englobees[1] in form.errors["gvvi_nom"])

    @patch('OSM_outils.OMSnx_enregistrement.OMSnx_enregistrement.sauvegarde_graphique')
    @patch('OSM_outils.OMSnx_enregistrement.OMSnx_enregistrement.recuperer_graphe_viaire_ville')
    def test_creation_form_plusieurs_ville_basic(self, mock_recuperer_graphe_viaire_ville, mock_sauvegarde_graphique):
        """
        Ce test va voir si plusieurs villes avec des noms connus de nominatim fonctionnent.
        """
        nom_fichier = "fusion_commune"
        nom_ville_englobees = ["Bolbec", "Gruchet-le-valasse"]
        mock_recuperer_graphe_viaire_ville.return_value = None
        str_entree_form = 'gvvi_nom=' + nom_fichier
        for nom_ville in nom_ville_englobees:
            str_entree_form = str_entree_form + "&gvvi_nom_ajout=" + nom_ville
        entree_form = QueryDict(str_entree_form)
        form = Graph_viaire_ville_informationForm(entree_form)
        self.assertTrue(form.is_valid())
        mock_sauvegarde_graphique.assert_called_once_with(ANY, nom_fichier)

    def test_creation_form_plusieurs_villes_du_meme_nom(self):
        """
        Cette méthode test s'il est possible d'avoir un ensemble de ville composée de villes du même nom.
        """
        nom_fichier = "fusion_commune"
        nom_ville_englobees = ["Bolbec", "Gruchet-le-valasse", "Bolbec", "Rouen"]
        str_entree_form = 'gvvi_nom=' + nom_fichier
        for nom_ville in nom_ville_englobees:
            str_entree_form = str_entree_form + "&gvvi_nom_ajout="+nom_ville
        entree_form = QueryDict(str_entree_form)
        form = Graph_viaire_ville_informationForm(entree_form)
        self.assertFalse(form.is_valid())
        self.assertEqual("plusieurs villes englobées portent le même nom", form.errors["__all__"][0])

   # test the form by giving it one city but osmnx save it with yes and no in the file for oneway key
    @patch('OSM_outils.OMSnx_enregistrement.OMSnx_enregistrement.sauvegarde_graphique')
    @patch('OSM_outils.OMSnx_enregistrement.OMSnx_enregistrement.recuperer_graphe_viaire_ville')
    @patch('OSM_outils.OSMnx_recuperation_graph_information.OSMnx_recuperation_graph_information.recuperation_information_graphe')
    def test_creation_erreur_fichier_graphml_contient_yes_no(self, mock_recuperer_graphe_viaire_ville, mock_sauvegarde_graphique, mock_recuperation_information_graphe):
        """
        Ce test va voir si lorsque la sauvegarde du fichier graphml contient yes et no, le formulaire modifie le fichier
        pour que les yes et no soient remplacés par True et False.
        """
        # récupération ville existante, pas enregistré dans le fichier ou la base de donnée
        nom_ville = "Vaudherland"
        entree_form = QueryDict('gvvi_nom=' + nom_ville)
        i_appelle = 0
        path_ville_erreur = settings.BASE_DIR.__str__() + "/recuperateur_reseau_viaire/Tests/Data/Vaudherland.graphml"
        path_ville_ok = settings.BASE_DIR.__str__() + "/recuperateur_reseau_viaire/Tests/Data/erreur_yes_no.graphml"
        # sauvegarde le fichier graphml contenant yes et no "erreur_yes_no.graphml"
        with open(path_ville_ok, "r") as file:
            content = file.readlines()
        with mock.patch.object(OMSnx_enregistrement, "chemin_vers_fichier_ville",
                               side_effect=[path_ville_ok, path_ville_erreur]):
            with mock.patch.object(OMSnx_enregistrement, "lire_graphe", side_effect=[None, None, ValueError, ValueError, None]):
                nom_ville = "erreur_yes_no"
                entree_form = QueryDict('gvvi_nom=' + nom_ville)
                form = Graph_viaire_ville_informationForm(entree_form)
                self.assertTrue(form.is_valid())

        # test si le fichier est lisible par osmnx (ne renvoie pas d'erreur)
        with mock.patch.object(OMSnx_enregistrement, "chemin_vers_fichier_ville",
                               side_effect=[path_ville_ok]):
            try:
                OMSnx_enregistrement.lire_graphe("erreur_yes_no")
            except AssertionError as a:
                self.fail("le fichier n'est pas lisible par osmnx")
        # remplace le fichier modifié par le formulaire par le fichier erreur d'origine "erreur_yes_no.graphml"
        with open(path_ville_ok, "w") as file:
            file.writelines(content)
