import os
from pdfreader import PDFDocument
import pypdf
from PIL import Image
from pillow_heif import register_heif_opener
from rest_framework.response import Response
from rest_framework import status
import base64




class ReceiptCheck:


    def get_file_type(self, file):
        try:       
            file_type = os.path.splitext(file)[1].lower()
            return file_type
        except Exception as e:
            return False
           


    def file_type_check(self, file, file_type):
            if file_type =='.heic':
                jpg_file = self.convert_into_jpg(file)  
                return jpg_file
            elif file_type =='.pdf':
                self.img_format = False
                self.check_pages(file)
            elif file_type not in ['.jpeg','.jpg', '.png']:
                return False
            return file



    def convert_into_jpg(self, file):
        try:
            register_heif_opener()
            temp_img = Image.open(file)
            original_filename = os.path.splitext(file)[0]
            temp_img.convert('RGB').save(original_filename + '.jpg')
            jpg_file_path = original_filename + '.jpg'
            temp_img.close()
            return jpg_file_path
        except Exception as e:
            return False
 


    def check_pages(self, file):
        try:
            fd = open(file, "rb")
            pdf_reader = PDFDocument(fd)
            all_pages = [p for p in pdf_reader.pages()]
            num_pages = len(all_pages)
            fd.close()
            return num_pages
        except Exception as e:
            return False
        
        

    def check_crypted(self, file): 
            if pypdf.PdfReader(file).is_encrypted:
                return True



    def file_with_mime(self, file_path, mime_type):
        with open(file_path, 'rb') as file:
            file_content = file.read()
            base64_content = base64.b64encode(file_content).decode('utf-8')
            data_url = f'data:{mime_type};base64,{base64_content}'
            return data_url
        
        

    def convert_to_base64(self, fileURL, file_type):
        if file_type in ('.jpeg', '.jpg', '.png'):
            return self.file_with_mime(fileURL, f'image/{file_type[1:]}')
        else:
            return None
        


    def file_to_base64(self, file_path):
            with open(file_path, "rb") as uploaded_file:
                encoded_string = base64.b64encode(uploaded_file.read())
                return encoded_string 
            


    def compress_image(self, file_path):
        try:
            with Image.open(file_path) as img:
                format = img.format
                quality = 100
    
                while os.path.getsize(file_path) > 4 * 1024 * 1024 and quality > 20:
                    quality -= 20
                    img.save(file_path, format=format, quality=quality)

                if os.path.getsize(file_path) > 4 * 1024 * 1024:
                    return False
                return True


        except Exception:
            return False
        



        
    def check_and_remove_converted_file(self, converted_file):
        if converted_file:
            os.remove(converted_file)




    def img_format_check(self, properly_formatted_file, converted_file):

        if os.path.getsize(properly_formatted_file) > 4 * 1024 * 1024:
            compress_result = self.compress_image(properly_formatted_file)

            if compress_result is False:     
                self.check_and_remove_converted_file(converted_file)
                return Response({'message': "Impossibile comprimere l'immagine alla dimensione necessaria. Per favore, riprova a riscattare la foto."}, status=status.HTTP_400_BAD_REQUEST)

        try:
            with Image.open(properly_formatted_file) as receipt:
                width, height = receipt.size              

                if not (50 <= width <=10000 and 50 <= height <= 10000):
                    self.check_and_remove_converted_file(converted_file)
                    return Response({'message': "Le dimensioni del file non sono valide, devono essere compresi tra 50px e 10000px. Per favore, verifica e riprova."}, status=status.HTTP_400_BAD_REQUEST)
                    
        except Exception:
            self.check_and_remove_converted_file(converted_file)
            return Response({'message': "Qualcosa è andato storto. Per favore, riprova."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            



    def pdf_format_check(self, properly_formatted_file):
            

        if self.check_crypted(properly_formatted_file):
            return Response({'message': "Il documento è cifrato e non può essere caricato."}, status=status.HTTP_400_BAD_REQUEST)  
             
        num_pages = self.check_pages(properly_formatted_file)
        if not num_pages:
             return Response({'message': "Qualcosa è andato storto. Per favore, riprova."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
        elif num_pages > 2:
            return Response({'message': "Il documento non soddisfa i requisiti necessari. Il numero di pagine supera due."}, status=status.HTTP_400_BAD_REQUEST)               
        



    def check(self, fileURL):
        properly_formatted_file = fileURL
        img_format = True
        base64_with_mime = ''
        converted_file = None


        file_type = self.get_file_type(properly_formatted_file)


        if not file_type:
             return Response({'message': "C'è stato un errore nel recupero del tipo di file. La preghiamo di riprovare più tardi."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


        if file_type in ('.jpeg', '.jpg', '.png'):
            base64_with_mime = self.convert_to_base64(properly_formatted_file, file_type)


        elif file_type =='.heic':
            properly_formatted_file = self.convert_into_jpg(fileURL)
            if not properly_formatted_file:
                 return Response({'message': "Si è verificato un errore durante la conversione del file. Per favore, riprova."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
            base64_with_mime = self.file_with_mime(properly_formatted_file, 'image/jpg')
            converted_file = properly_formatted_file


        elif file_type =='.pdf':
            pdf_result = self.pdf_format_check(properly_formatted_file)

            if isinstance(pdf_result, Response):
                return pdf_result
            
            img_format = False
            base64_with_mime = self.file_with_mime(properly_formatted_file, 'application/pdf') 

     
        elif file_type not in ['.jpeg','.jpg', '.png']:
            return Response({'message': "Il tipo di file selezionato non è supportato. Per favore, scegli un altro file."}, status=status.HTTP_400_BAD_REQUEST)
        

        if img_format:
            img_result = self.img_format_check(properly_formatted_file, converted_file)

            if isinstance(img_result, Response):
                return img_result
            



        base64_file = self.file_to_base64(properly_formatted_file).decode('utf-8')

        self.check_and_remove_converted_file(converted_file)

        return base64_file, base64_with_mime






