import pikepdf, re, os
from flask_mail import Message
from app import mail
from app.models import licenze
from PyPDF2 import PdfWriter, PdfReader
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter

def insert_pin(cliente, files): # prende i dati dal form e per ogni file inserisce il relativo PIN nel DB ed invia una mail a MAIL_DEST
    files_names = upload(files) # decifro i file e li salvo su disco
    indice = 1 # creo un indice - parto da 1 perchè è umano
    pdf_file = []
    for file in files_filenames: # ciclo sui singoli file
        dati = converti_licenza(read_pdf(file)) # creo i dati variabili
        pdf_file.append(scrivi_pdf(cliente, dati, indice)) # creo il pdf con il pin e lo metto nella lista
    subject = create_subject(cliente)
    
 
def create_subject(cliente):
    return('Invio PIN licenza ML - Nostro riferimento: '+cliente['ns']+' - Cliente: '+cliente['rs'])

def upload(files): #legge i file caricati e li salva senza password e ritorna la lista dei nuovi nomi
    files_filenames = []
    for file in files:
        file_filename = secure_filename(file.filename)
        pdf = pikepdf.open(file_filename,password="FSPA7691")
        file_dec = file_filename+"_dec.pdf"
        pdf.save(file_dec)
        files_filenames.append(file_dec)
    return files_filenames

def send_email(subject, text_body, html_body, files): #invia la mail con i PIN
    msg = Message(subject, sender=app.config['MAIL_SENDER'], recipients=app.config['MAIL_DEST'])
    msg.body = text_body
    msg.html = html_body
    for file in files: # aggiungo gli allegati
         mimetype = file.content_type
         filename = secure_filename(file.filename)
         msg.attachments = file
         msg.attach(filename, mimetype)
    istruzioni = app.config['BASE_FOLDER']+app.config['ISTR_OPER'] # identifico il file delle istruzioni
    msg.attachments = istruzioni
    msg.attach(istruzioni, istruzioni.content_type) # aggiungo il file delle istruzioni
    mail.send(msg) #devo verificare l'invio e ritornare qualcosa

def read_pdf(file): # estrae il PIN ed il nome della licenza dal file PDF e li ritorna come due elementi di una lista
    Pdf = PyPDF2.PdfReader(file)
    os.remove(file) # dopo averlo letto elimino il file da disco
    try:
     page1 = Pdf.pages[1]
    except IndexError as error:
     # devo ritornare un errore in qualche modo
     #print("Il file '"+file+"' non sembra essere un file contenente PIN per centrali ML")
     exit()
    testo1 = page1.extract_text()
    #estraggo il pin
    p = re.compile(r'[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{4}') #cerco un'espressione che sia come quella del PIN aaaa-aaaa-aaaa-aaaa
    try:
     dati = [append(re.findall(p, testo1)[0])]
    except IndexError as error:
     # devo ritornare un errore in qualche modo
     #print("Il file '"+file+"' non sembra essere un file contenente PIN per centrali ML")
     exit()
    page0 = Pdf.pages[0]
    testo0 = page0.extract_text()
    matchf = re.search(r'\d{2}/\d{2}/\d{4}', testo0) # nel testo estratto il nome della licenza precede la data. cerco quindi un'espressione che sia una data mm/gg/aaaa
    fine = matchf.start() # segno l'inizio della data come fine del testo da estrarre
    matchi = re.search('SARVAM ', testo0) # tutti i nomi delle licenze iniziano con SARVAM
    inizio = matchi.end() #segno la fine di SARVAM come inizio del testo da estrarre
    dati.append(testo0[inizio:fine].replace("\n","")) 
    return dati

def converti_licenza(dati): # prendo i dati del pdf Matrix e li trasformo negli equivalenti Fitre
    licenza = licenze.search_desM(dati[1])  # cerco nel DB la licenza in base al nome Matrix
    return [dati[0], licenza.codFitre, licenza.desFitre]

def crea_istruzioni(): # trasforma il pdf con le istruzioni operative in un allegato per le mail e lo ritorna
    part = MIMEBase('application', "octet-stream")
    filename = app.config['BASE_FOLDER']+app.config['ISTR_OPER']
    with open(filename, "rb") as file:
        part.set_payload(file.read())
        encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment', filename=filename.replace('_temp', ''))
        return part

def crea_filepin(nomefile): # trasforma il pdf con i dati PIN in un allegato per le mail e lo ritorna
    part = MIMEBase('application', "octet-stream")
    with open(nomefile, "rb") as file:
       part.set_payload(file.read())
       encoders.encode_base64(part)
       part.add_header('Content-Disposition', 'attachment', filename=nomefile.replace(app.config['BASE_FOLDER'], ''))
    return part

def scrivi_pdf(cliente, dati, indice): # crea il modulo pdf con i dati del cliente ed il PIN, dandogli un nome file indicizzato (nel caso di PIN multipli sullo stesso ordine; ritorna il nome file
    # scrivo la parte variabile
    packet = io.BytesIO()
    can = canvas.Canvas(packet, pagesize=letter)
    can.setFont('Courier-Bold', 11)
    can.drawString(75, 475, dati[1]) # codice licenza
    can.drawString(135, 475, dati[2]) # descrizione licenza
    can.drawString(390, 475, dati[0]) # PIN licenza
    can.drawString(180, 530, cliente['oc']) # numero ordine cliente
    can.drawString(425, 530, cliente['doc']) # data ordine cliente
    can.drawString(140, 610, cliente['ns']) # numero ordine Fitre
    can.drawString(120, 640, date.today().strftime("%d/%m/%Y")) # data di oggi
    can.setFont('Courier-Bold', 10)
    can.drawString(355, 675, cliente['rs']) # ragione sociale
    can.drawString(335, 652, cliente['em']) # email
    can.save()
    packet.seek(0) #move to the beginning of the StringIO buffer
    PDF_var = PdfReader(packet) # creo il PDF con i soli dati variabili
    modulo = PdfReader(open(app.config['BASE_FOLDER']+app.config['MODULO_PIN'], "rb")) # apro il modulo per invio a cliente
    page = modulo.pages[0] # mi metto sulla prima pagina
    page.merge_page(PDF_var.pages[0]) #aggiungo il testo variabile
    output = PdfWriter() # creo un nuovo file
    output.add_page(page) # ed aggiungo la pagina completa dei dati
    nomefile = app.config['UPLOAD_FOLDER']+"/PIN_"+dati[1]+"_"+cliente['ns']+"_"+"+str(i).pdf" #creo il file finale dandogli come nome, il nostro riferimento ordine e l'indice incrementale
    outputStream = open(nomefile, "wb") # creo il file sul disco
    output.write(outputStream) # scrivo il PDF sul file
    outputStream.close() # chiudo il file sul disco
    return nomefile
    