import os
import pickle
import pandas as pd

from presidio_analyzer import AnalyzerEngine
from presidio_anonymizer import AnonymizerEngine

from faker import Faker
from faker.providers import internet


# Funkcja używana do pseudonimizowania tekstu zawierającego adresy e-mail 
def anonymizeEmail(text_to_anonymize, country):
    # Zainicjuj obiekt Faker
    fake = Faker(faker_locales_dict[country])
    fake.add_provider(internet)

    analyzer_results = analyzer.analyze(text=text_to_anonymize, entities=["EMAIL_ADDRESS"], language='en')
    
    matched_emails = {}
    for match in analyzer_results:
        email = text_to_anonymize[match.start:match.end]
        
        if email not in emails_dict:
            fake_email = fake.safe_email()

            while (fake_email in emails_dict.values()) or (fake_email in emails_dict):
                fake_email = fake.safe_email()
                
            emails_dict[email] = fake_email
            matched_emails[email] = fake_email
        else:
            fake_email = emails_dict[email]
            matched_emails[email] = fake_email

    anonymized_result = text_to_anonymize
    for email in matched_emails:
        anonymized_result = anonymized_result.replace(email, matched_emails[email])

    return anonymized_result

# Funkcja używana do pseudonimizowania tekstu zawierającego nazwiska
def anonymizeName(text_to_anonymize, country):
    # Zainicjuj obiekt Faker
    fake = Faker(faker_locales_dict[country])
    
    analyzer_results = analyzer.analyze(text=text_to_anonymize, entities=["PERSON"], language='en')

    matched_names = {}
    for match in analyzer_results:
        name = text_to_anonymize[match.start:match.end]
        
        if name not in names_dict:
            fake_name = fake.name()
            
            while (fake_name in names_dict.values()) or (fake_name in names_dict):
                fake_name = fake.name()

            names_dict[name] = fake_name
            matched_names[name] = fake_name
        else:
            fake_name = names_dict[name]
            matched_names[name] = fake_name

    anonymized_result = text_to_anonymize
    for name in matched_names:
        anonymized_result = anonymized_result.replace(name, matched_names[name])

    return anonymized_result


# W celu testowania możesz załadować zawartość pliku Excela bezpośrednio tutaj 
# Wystarczy odkomentować poniższe 2 wiersze. 
# # Załaduj zawartość pliku Excel do ramki danych 
# dataset = pd.read_excel(r'D:\<twoja-ścieżka>\Chapter06\CustomersCreditCardAttempts.xlsx', engine='openpyxl')

# Załaduj słowniki mapowania z plików PKL, jeśli istnieją, w przeciwnym razie utwórz puste słowniki
pkls_path = r'D:\<twoja-ścieżka>\Chapter06\pkls'
emails_dict_pkl_path = os.path.join(pkls_path, 'emails_dict.pkl')
names_dict_pkl_path = os.path.join(pkls_path, 'names_dict.pkl')

if os.path.isfile(emails_dict_pkl_path):
    emails_dict = pickle.load( open(emails_dict_pkl_path, "rb") )
else:
    emails_dict = {}

if os.path.isfile(names_dict_pkl_path):
    names_dict = pickle.load( open(names_dict_pkl_path, "rb") )
else:
    names_dict = {}

# Zdefiniuj słowniki lokalizacyjne i językowe 
faker_locales_dict = {'UNITED STATES': 'en_US', 'ITALY': 'it_IT', 'GERMANY': 'de_DE'}



# Zainicjuj analizator i anonimizator Presidio 
# https://microsoft.github.io/presidio/supported_entities/
analyzer = AnalyzerEngine()
anonymizer = AnonymizerEngine()

# Utwórz kopię źródłowego zestawu danych 
df = dataset.copy()

# Zastosuj funkcję anonymizeName dla każdej wartości kolumny Name
df.Name = pd.Series( [anonymizeName(text, country) for (text, country) in zip(df['Name'], df['Country'])] )

# Zastosuj funkcję anonymizeEmail dla każdej wartości kolumny Email 
df.Email = pd.Series( [anonymizeEmail(text, country) for (text, country) in zip(df['Email'], df['Country'])] )

# Kolumna Notes jest typu danych 'object', ponieważ zawiera dużo wartości NaN i 
# moduł pandas nie rozpoznaje jej jako tekstu. Dlatego należy przekonwertować je na tekst,
# aby można je było zanonimizować. Następnie należy zastąpić te wartości wartością zanonimizowaną
df.Notes = pd.Series( [anonymizeName(text, country) for (text, country) in zip(df['Notes'].astype('str'), df['Country'])] )
df.Notes = pd.Series( [anonymizeEmail(text, country) for (text, country) in zip(df['Notes'].astype('str'), df['Country'])] )


# # Aby pakiet pandas nie obcinał ciągów w komórkach 
# pd.set_option('display.max_colwidth', None)

# # Wyświetlenie obu ramek danych
# dataset
# df

# Zapisz słowniki emaili i nazwisk do plików PKL
pickle.dump( emails_dict, open(emails_dict_pkl_path, "wb") )
pickle.dump( names_dict, open(names_dict_pkl_path, "wb") )
