import json

class Contact:
    def __init__(self, name: str, phone: str, email: str):
        self.name = name
        self.phone = phone
        self.email = email

    def __iter__(self):
        yield self.name
        yield self.phone
        yield self.email

    def __repr__(self) -> str:
        return f"{self.name} - {self.phone} - {self.email}"
    
    def __eq__(self, other: "Contact"):
        return self.name == other.name\
            and self.phone == other.phone\
            and self.email == other.email
    
    def serialized(self):
        """Converti la classe en dictionnaire JSONable"""
        return {"Name": self.name, "Phone": self.phone, "Email": self.email}

    @classmethod
    def deserialized(cls, dictionnary):
        """Lis un JSON pour le retranscrire en classe Contact"""
        return cls(name= dictionnary["Name"], phone= dictionnary["Phone"], email= dictionnary["Email"])
    
class Repertory:
    def __init__(self, name: str):
        self.name = name
        self.contacts: list[Contact] = self.load()

    def __iter__(self):
        return iter(self.contacts)
    
    def __getitem__(self, index: int) -> Contact:
        return self.contacts[index]

    def add_contact(self, contact: Contact):
        if contact in self.contacts:
            return f"{contact.name} est déjà dans le répertoire."
        self.contacts.append(contact)
        self.save()
        return f"Nouveau contact :\nNom      : {contact.name}\nNuméro   : {contact.phone}\nCourriel : {contact.email}"
    
    def delete_contact(self, contact_info: str):
        for contact in self.contacts:
            if contact.name.lower()  == contact_info.lower()\
            or contact.phone.lower() == contact_info.lower()\
            or contact.email.lower() == contact_info.lower():
                self.contacts.remove(contact)
                self.save()
                return f"{contact.name} a été supprimé du répertoire."
        return f"{contact.name} n'est pas dans le répertoire."
    
    def search_contact(self, research_str: str):
        results = []
        for contact in self.contacts:
            if research_str.lower() in contact.name.lower()\
            or research_str.lower() in contact.phone.lower()\
            or research_str.lower() in contact.email.lower():
                results.append(contact)
        return results if len(results) > 0 else "Pas de résultat."
    
    def display_contacts(self):
        results = []
        for idx, contact in enumerate(self.contacts):
            results.append(
                f"----- Contact n°{idx + 1} -----\n"
                f"Nom      : {contact.name}\n"
                f"Numéro   : {contact.phone}\n"
                f"Courriel : {contact.email}\n"
                " "
            )
        return "".join(results) if results else "Aucun contact dans le répertoire."

    # Sauvegarde des livres dans un JSON pour persistance des données

    def save(self):
        """Inscris dans un fichier JSON le contenu de la bibliothèque"""
        contact_dict = [contact.serialized() for contact in self.contacts]
        with open("contacts.json", "w") as json_file: # a pour append, w pour write
            json.dump(contact_dict, json_file, indent= 4)

    def load(self) -> list[Contact]:
        """Récupère le contenu d'un fichier JSON"""
        with open("contacts.json") as json_file:
            return json.load(json_file, object_hook= Contact.deserialized)