from django.shortcuts import render
from django.http import HttpResponse,HttpResponseRedirect,FileResponse
from django.urls import reverse
from django.db import IntegrityError

from .models import *
from config.views import *
from att.views import *

from django.conf import  settings
from django.conf.urls.static import static
from django.contrib.auth import authenticate
import mimetypes
from random import randint
import csv
import time
import datetime
import zipfile

#pip install python-codicefiscale
from codicefiscale import codicefiscale

import os

# come sono gestiti i file nella configurazione:
# MEDIA_ROOT=os.path.join(settings.BASE_DIR,'static/upload')
# che diventa = os.path.join(settings.BASE_DIR,getConfig('DocPath'))
# inoltre devo aver fatto qualche casino oggi 9.8.24 con i copia e incolla. ho dovuto rivedere tutto il file
# il terrore si impossessa di me. sta storia del cvs non e' esattamente chiara

def delete_file(documento):
  # questo blocco rimuove fisicamente il file prima della sua rimozione logica nel db
  file_path = os.path.join(settings.BASE_DIR,getConfig('DocPath'),documento.utente.azienda.partitaiva,documento.utente.codicefiscale,documento.storage)
  print('Path completa:',file_path)
  if os.path.isfile(file_path):
    print('rimozione fisica file:',file_path)  
    try:
      os.remove(file_path)
    except OSError as ose:
      print('errore nella rimozione del file:',ose)

def download_file(request,uid):
    utente = Utenti.objects.get(pk=uid)
    file_path = os.path.join(settings.BASE_DIR,getConfig('DocPath'),documento.utente.azienda.partitaiva,documento.utente.codicefiscale,utente.storage)
    print('Path completa da Basedir:',file_path)
    if utente.storage and os.path.isfile(file_path):
      try:
        fl = open(file_path, 'rb')
      except Exception as er:
        print('errore',er)
        data=dict()
        data['errore']="File non esistente o non ancora disponibile"
        data['utente'] = utente
        return render(request,'welcome.error.html',data)
    else:
      print('il file non esiste',file_path)
      data=dict()
      data['errore']='File non esistente o non ancora disponibile'
      data['utente'] = utente
      return render(request,'welcome.error.html',data)

    mime_type, _ = mimetypes.guess_type(file_path)
    print('file',file_path,mime_type)
    response = FileResponse(open(file_path,'rb'),content_type='application/pdf',as_attachment=False)
    #response['Content-Disposition'] = "attachment; filename=%s" % u.documento
    return response
  
def upload_file(uploaded_file,utente,originale=False):
  '''
  caricamento files
  '''
  stored_file = ''.join((str(time.time()),'.saved'))
  fl_path = os.path.join(settings.BASE_DIR,getConfig('DocPath'))
  print('nome file',uploaded_file.name,stored_file)

  nomefile=None
  if originale:
    nomefile = uploaded_file.name
  else:
    nomefile = stored_file

  # vediamo se caricare o meno.
  # in questo caso, se il documento esiste gia', non lo carica.
  # come facciamo a stabilire se il documento esiste gia'?
  # fl_path = corrisponde a media.ROOT (che mi domando se non e' il caso di spostarlo nella configurazione)
  # azienda.partitaiva
  # utente.codicefiscale (prima era "record" e mi sono deciso a cambiarlo)

  try:
    print(os.path.join(fl_path,utente.azienda.partitaiva))
    os.mkdir(os.path.join(fl_path,utente.azienda.partitaiva))
  except FileExistsError as fee:
    print(os.path.join(fl_path,utente.azienda.partitaiva),"esistente")
  try:
    os.mkdir(os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale))
  except fileexistserror as fee:
    print(os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale),"esistente")

  with open(os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale,nomefile),'wb+') as d:
    for chunk in uploaded_file.chunks():
      d.write(chunk)

  if originale:
    return os.path.join(fl_path,utente.azienda.partitaiva,utente.codicefiscale,nomefile)
  return stored_file

def upload_file_indice(uploaded_file):
  # caricamento file indice (gestito in modo diverso)

  stored_file = ''.join((str(time.time()),'.saved'))
  fl_path = os.path.join(settings.BASE_DIR,getConfig('DocPath'),getConfig('DocPathIndex'))
  print('nome file',uploaded_file.name,stored_file)

  # verifica l'esistenza della directory
  try:
    os.mkdir(fl_path)
  except FileExistsError as fee:
    print(fl_path,"esistente")

  print('file_memorizzato',os.path.join(fl_path,stored_file))

  with open(os.path.join(fl_path,stored_file),'wb+') as d:
    for chunk in uploaded_file.chunks():
      d.write(chunk)

  return stored_file

def associafile_a_utente(singolodocumento,request,utente,azienda=None,sede=None,descrizione=None,amministratore=None,listaok=None,listanotok=None,pertutti=False):
  risultato = upload_file(singolodocumento,utente)
  documento = Documento()
  documento.dataupload = datetime.datetime.now()
  documento.utente = utente

  if pertutti: 
    documento.documento = "".join((utente.codicefiscale.strip(),"_",singolodocumento.name))
  else: 
    documento.documento = singolodocumento.name

  print('documento.documento',documento.documento)
  documento.storage = risultato
  documento.descrizione = descrizione
  try:
    documento.save()
    setLog(8,azienda=azienda,sede=sede,utente=utente,documento=documento,amministratore=amministratore)
    listaok.append(documento)
  except IntegrityError as ie:
    print("problema di integrita', il file esiste",ie)
    listanotok.append(documento)

##################################################################################
# carica file multipli. Utilizzato prevalentemente dalla gestione documenti.
def save_and_load_file_multiple(listadocumenti,request,utente,azienda=None,sede=None,descrizione=None,amministratore=None,pertutti=False):
  listaok = list()
  listanotok = list()

  if azienda: print('Caricamento Multiplo,azienda',azienda.nome)
  if sede: print('Caricamento Multiplo,sede',sede.nome)

  for singolodocumento in listadocumenti:
    print('singolodocumento',singolodocumento)
    for ut in utente:
      if not pertutti:
        if ut.codicefiscale.strip() in singolodocumento.name:
          print('associa documento CON riferimento a codice fiscale')
          associafile_a_utente(singolodocumento,request,ut,azienda,sede,descrizione,amministratore,listaok,listanotok)
        else:
          print('il codice fiscale',ut.codicefiscale.strip()," non si trova in ",singolodocumento.name)
      else:
        print('associo documento SENZA riferimento a codice fiscale')
        associafile_a_utente(singolodocumento,request,ut,azienda,sede,descrizione,amministratore,listaok,listanotok,pertutti)

  print('liste',listaok,listanotok)
  return (listaok,listanotok)

#carica un singolofile - utilizzato prevalentemente nella pagina utente
def save_and_load_file_single(listadocumenti,request,utente,azienda=None,sede=None,descrizione=None,amministratore=None):
  listaok = list()
  listanotok = list()
  for singolodocumento in listadocumenti:
    print('singolodocumento',singolodocumento,descrizione)
    risultato = upload_file(singolodocumento,utente)
    documento = Documento()
    documento.dataupload = datetime.datetime.now()
    documento.utente = utente
    documento.documento = singolodocumento.name
    documento.storage = risultato
    documento.descrizione = descrizione
    try:
      documento.save()
      setLog(8,azienda=azienda,sede=sede,utente=utente,documento=documento,amministratore=amministratore)
      listaok.append(documento)
    except IntegrityError as ie:
      print("problema di integrita', il file esiste",ie)
      listanotok.append(documento)
  return (listaok,listanotok)

#file_indice: contiene l'elenco dei nominativi da gestire.
def save_and_load_file_indice(request,fileindice,azienda=None,sede=None):
  print('nome indice caricato',fileindice.name)
  if azienda: print('azienda',azienda.nome)
  if sede: print('sede',sede.nome)

  file_memorizzato = upload_file_indice(request.FILES['indice'])
  fl_path = os.path.join(getConfig('DocPath'),getConfig('DocPathIndex'))
  risultato = None
  with open(os.path.join(fl_path,file_memorizzato),'rb') as ind:
    risultato = ind.read()
    risultato = risultato.decode('utf-8',errors='replace')
    if isinstance(risultato,str):
      risultato = risultato.encode('utf8')

    with open(os.path.join(fl_path,''.join((file_memorizzato,'.cvtd'))),'wb') as ind:
      ind.write(risultato)
      print('una volta convertito, passiamo oltre')
    
    with open(os.path.join(fl_path,''.join((file_memorizzato,'.cvtd'))),'rt') as ind:
        spamreader = csv.reader(ind,delimiter=';')
        errori = list()
        count = 0
        for sr in spamreader:
          salvare = False
          count +=1
          if count==1: continue
          print(count,'sr',sr,len(sr))

          if len(sr) >= 1: # la lunghezza del record segnala qualcosa
            print('lunghezza ok',sr[0])
            utente = None

            #sr = sr[0].split(';')
 
            print('codice fiscale',sr[0].strip().upper())
            try:
              utente = Utente.objects.get(codicefiscale=sr[1].strip().upper())
            except Utente.DoesNotExist as dne:
              print('Utente non trovato')
              utente = Utente()
              if azienda: utente.azienda = azienda
              if sede: utente.sede = sede

              utente.nome = sr[0].title()
              utente.codicefiscale=sr[1].upper()

              for fmt in ('%d/%m/%y','%d/%m/%Y','%d-%m-%y','%d-%m-%Y'):
                try:
                  data_convertita =  datetime.datetime.strptime(sr[2],fmt)
                  print('data convertita',data_convertita)
                  utente.datanascita = data_convertita
                except ValueError as ve:
                  print('errore con la data di nascita',ve)

              utente.luogonascita = sr[3].title()
              utente.mail = sr[4].lower()

              # ricerca sede: se il codice estratto nella colonna corrisponde...
              tmp_sede = sr[5]
              lista_sede = azienda.sede_set.all()
              for ls in lista_sede:
                if tmp_sede == ls.identificativo:
                  utente.sede = ls

              utente.inserimento = datetime.datetime.today().strftime("%Y-%m-%d")

              utente.pin = str(randint(100000,999999))
              utente.save()

def PrepareZipFile(listafile=[]):
  zip_path = os.path.join(settings.BASE_DIR,getConfig('DocZipFile'))
  print("zip_path:",zip_path)

  # verifica l'esistenza della directory
  try:
    os.mkdir(zip_path)
  except FileExistsError as fee:
    print(zip_path,"esistente")
  filename = ''.join((str(time.time()),'.zip'))

  with zipfile.ZipFile(os.path.join(zip_path,filename),'w') as zip:
    for lf in listafile:
      d = Documento.objects.get(pk=lf)
      file2zip = os.path.join(settings.BASE_DIR,getConfig('DocPath'),d.utente.azienda.partitaiva,d.utente.codicefiscale,d.storage)
      zip.write(file2zip,arcname=d.documento)
    print('path completa',file2zip)
    print('file completo',os.path.join(zip_path,filename))
  return (zip_path,filename)


