from django.shortcuts import render
from django.views.generic import View
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
import json

from .serializers import *
from .filehandler import *
from .fileconverter.converter import *
from .enums import *

file_handler = FileHandler()

pdfconverter = PdfConverter()
docconverter = DocConverter()
docxconverter = DocxConverter()
txtconverter = TxtConverter()
odtconverter = OdtConverter()

# Create your views here.
class IndexView(View):
    def get(self, request):
        return render(request, 'index.html')

class Get_All_Uploaded_Files(APIView):
    serializer_class = DocumentSerializer

    def get(self, request, *args, **kwargs):
        try:
            li = Document.objects.all()
            serializer = self.serializer_class(li, many=True)
            
            if serializer.data != []:
                return Response(status=status.HTTP_200_OK, data={"status": status.HTTP_200_OK, "details": serializer.data})
            else:
                return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Empty Docs List"})
        
        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})
        
class Upload_And_Convert_File(APIView):
    serializer_class = DocumentUploadAndConvertSerializer

    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            file = ''
            if 'file' in data:
                if data['file'] != '':
                    file = data['file']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "file".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "file" is not in the data.'})
            print(f"File: {file}")
            
            filetype = ''
            if 'fileType' in data:
                if data['fileType'] != '':
                    filetype = data['fileType']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "fileType".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "fileType" is not in the data.'})
            print(f"Output Filetype: {filetype}")
            
            if file_handler.check_doc_data(doc=file):

                if file_handler.check_doc_type(doc=file):

                    file_handler.get_docID_uploadtime(output_filetype=filetype, file_category=FileCategory.INPUT_BASE64)

                    if file_handler.convert_file_to_base64(file_category=FileCategory.INPUT_BASE64, doc=file):

                        if file_handler.save_to_temp_folder():

                            print(f"Temp Input Folderpath: {file_handler.temp_folderpath}")

                            if file_handler.inputfiletype[0] == FileFormat.PDF.value:
                                convertor = pdfconverter
                            elif file_handler.inputfiletype[0] == FileFormat.DOC.value:
                                convertor = docconverter
                            elif file_handler.inputfiletype[0] == FileFormat.DOCX.value:
                                convertor = docxconverter
                            elif file_handler.inputfiletype[0] == FileFormat.TXT.value:
                                convertor = txtconverter
                            elif file_handler.inputfiletype[0] == FileFormat.ODT.value:
                                convertor = odtconverter
                            else:
                                return Response(status=status.HTTP_406_NOT_ACCEPTABLE, data={"status": status.HTTP_406_NOT_ACCEPTABLE, "details": f'Invalid datatype: {file_handler.outputfiletype}.'})
                            
                            result = convertor.convert(file_handler.temp_folderpath + file_handler.inputfilename[0] + file_handler.inputfiletype[0], file_handler.outputfiletype)
                            print(result)
                            
                            if result[1]:
                                if file_handler.convert_file_to_base64(FileCategory.OUTPUT):
                                    # file_handler.delete_temp_folder()

                                    if file_handler.outputfilestream != []:
                                
                                        post_data = {
                                            'docID': file_handler.docID, 
                                            'uploadtime': file_handler.uploadtime,
                                            'inputfolderpath': file_handler.inputfolderpath, 
                                            'inputfilename': json.dumps(file_handler.inputfilename), 
                                            'inputfiletype': json.dumps(file_handler.inputfiletype), 
                                            'inputfilestream': json.dumps(file_handler.inputfilestream), 
                                            'outputfiletype': file_handler.outputfiletype,
                                            'outputfilestream': json.dumps(file_handler.outputfilestream)
                                            }
                                        
                                        # print(f"Post Data: {post_data}")
                                        
                                        serializer = self.serializer_class(data=post_data)
                                        # print("Serializer:\n", serializer)
                                        if serializer.is_valid():
                                            serializer.save()
                                            return Response(status=status.HTTP_201_CREATED, data={"status": status.HTTP_201_CREATED, "details": serializer.data})
                                        
                                        print("Failed: Data is not valid.")
                                        return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Data is not valid."})
                                    
                                    print("Failed: Response could not be obtained.")
                                    return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Response could not be obtained."})
                    
                                print("Failed: Data could not be converted to bytestream.")
                                return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": "Data could not be converted to bytestream."})
                                
                            file_handler.delete_temp_folder()
                            print(f"Failed: Error: {result[0]}.")
                            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": f"Error: {result[0]}."})
                        
                        print("Failed: Data could not be saved to temporary folder.")
                        return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Data could not be saved to temporary folder."})
                    
                    print("Failed: Data could not be converted to base64 format.")
                    return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": "Data could not be converted to base64 format."})
                
                print("Failed: Invalid filetype.")
                return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_206_PARTIAL_CONTENT, "details": "Invalid filetype."})
            
            print(f"Failed: Empty File Data: {str(file)}.")
            return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": f"Empty File Data: {str(file)}."})
        
        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})
        
class Upload_And_Convert_Folder(APIView):
    serializer_class = DocumentUploadAndConvertSerializer

    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            folderpath = ''
            if 'folderPath' in data:
                if data['folderPath'] != '':
                    folderpath = data['folderPath']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "folderPath".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "folderPath" is not in the data.'})
            print(f"Input Folderpath: {folderpath}")
            
            filetype = ''
            if 'fileType' in data:
                if data['fileType'] != '':
                    filetype = data['fileType']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "fileType".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "fileType" is not in the data.'})
            print(f"Output Filetype: {filetype}")

            if file_handler.check_folder_data(self, folderpath):
            
                type_check_result, skipped_files = file_handler.check_folder_type(folderpath=folderpath, output_filetype=filetype)
                if type_check_result:
                    file_handler.get_docID_uploadtime(output_filetype=filetype, file_category=FileCategory.INPUT_FOLDERPATH)

                    if file_handler.convert_file_to_base64(file_category=FileCategory.INPUT_FOLDERPATH):

                        if file_handler.save_to_temp_folder():
                            print(f"Temp Input Folderpath: {file_handler.temp_folderpath}")
                            results = []

                            for num in range(len(file_handler.inputfilename)):
                                if file_handler.inputfiletype[num] == FileFormat.PDF.value:
                                    convertor = pdfconverter
                                elif file_handler.inputfiletype[num] == FileFormat.DOC.value:
                                    convertor = docconverter
                                elif file_handler.inputfiletype[num] == FileFormat.DOCX.value:
                                    convertor = docxconverter
                                elif file_handler.inputfiletype[num] == FileFormat.TXT.value:
                                    convertor = txtconverter
                                elif file_handler.inputfiletype[num] == FileFormat.ODT.value:
                                    convertor = odtconverter
                                else:
                                    return Response(status=status.HTTP_406_NOT_ACCEPTABLE, data={"status": status.HTTP_406_NOT_ACCEPTABLE, "details": f'Invalid datatype: {file_handler.outputfiletype}.'})
                                
                                result = convertor.convert(file_handler.temp_folderpath + file_handler.inputfilename[num] + file_handler.inputfiletype[num], file_handler.outputfiletype)
                                results.append(result[1])
                                print(f"Result No. {num + 1}: {result}")
                            
                            if False not in results:
                                if file_handler.convert_file_to_base64(FileCategory.OUTPUT):
                                    file_handler.delete_temp_folder()

                                    if file_handler.outputfilestream != []:
                                
                                        post_data = {
                                            'docID': file_handler.docID, 
                                            'uploadtime': file_handler.uploadtime,
                                            'inputfolderpath': file_handler.inputfolderpath, 
                                            'inputfilename': json.dumps(file_handler.inputfilename), 
                                            'inputfiletype': json.dumps(file_handler.inputfiletype), 
                                            'inputfilestream': json.dumps(file_handler.inputfilestream), 
                                            'outputfiletype': file_handler.outputfiletype,
                                            'outputfilestream': json.dumps(file_handler.outputfilestream),
                                            'skippedfiles': json.dumps(skipped_files)
                                            }
                                        
                                        # print(f"Post Data: {post_data}")
                                        
                                        serializer = self.serializer_class(data=post_data)
                                        # print("Serializer:\n", serializer)
                                        if serializer.is_valid():
                                            serializer.save()
                                            return Response(status=status.HTTP_201_CREATED, data={"status": status.HTTP_201_CREATED, "details": serializer.data})
                                        
                                        print("Failed: Data is not valid.")
                                        return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Data is not valid."})
                                    
                                    print("Failed: Response could not be obtained.")
                                    return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Response could not be obtained."})
                    
                                print("Failed: Data could not be converted to base64 format.")
                                return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": "Data could not be converted to base64 format."})
                                
                            file_handler.delete_temp_folder()
                            print(f"Failed: Error: {[result[0] for result in results if result[1] == False]}.")
                            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": f"Error: {result[0]}."})
                        
                        print("Failed: Data could not be saved to temporary folder.")
                        return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Data could not be saved to temporary folder."})
                    
                    print("Failed: Data could not be converted to base64 format.")
                    return Response(status=status.HTTP_412_PRECONDITION_FAILED, data={"status": status.HTTP_412_PRECONDITION_FAILED, "details": "Data could not be converted to base64 format."})
                
                print("Failed: Invalid filetype.")
                return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_206_PARTIAL_CONTENT, "details": "Invalid filetype."})
            
            print("Failed: Empty Folder.")
            return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Empty Folder."})
        
        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})
        
class Download_File(APIView):

    def post(self, request, *args, **kwargs):
        try:
            data = request.data

            docId = ''
            if 'docID' in data:
                if data['docID'] != '':
                    docId = data['docID']
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "docID".'})
            else:
                return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Key "docID" is not in the data.'})
            print(f"Document ID: {docId}")

            # output_filename = None
            # if 'fileName' in data:
            #     if data['fileName'] != '':
            #         output_filename = data['fileName']
            #     else:
            #         return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "fileName".'})

            # output_filepath = None
            # if 'filePath' in data:
            #     if data['filePath'] != '':
            #         output_filepath = data['filePath']
            #     else:
            #         return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": 'Data is not valid. Empty data in the key "filePath".'})
                
            # print(f"Output Filename: {output_filename}")
            # print(f"Output Filepath: {output_filepath}")

            docId_list = Document.objects.values_list('docID', flat=True)
            if docId in docId_list:

                select_item = Document.objects.filter(docID=docId).order_by('uploadtime').last()
                file_handler.assign_select_item_details(select_item.docID, select_item.uploadtime, select_item.inputfolderpath, 
                                                    json.loads(select_item.inputfilename), json.loads(select_item.inputfiletype), 
                                                    json.loads(select_item.inputfilestream), select_item.outputfiletype,
                                                    json.loads(select_item.outputfilestream))

                if file_handler.outputfilestream != []:
                    file_handler.declare_output_filepath_details()
                    
                    if file_handler.compress_output_files_for_download():
                        # select_item.outputfolderpath = file_handler.outputfolderpath
                        select_item.outputfilename = file_handler.outputfilename
                        select_item.outputfiletype = file_handler.outputfiletype
                        select_item.downloadfiledata = file_handler.downloadfiledata
                        select_item.save()

                        return Response(status=status.HTTP_201_CREATED, 
                                        data={"status": status.HTTP_201_CREATED, 
                                              "details": {
                                                  'docID': select_item.docID, 
                                                  'output_filename': select_item.outputfilename, 
                                                  'output_filetype': select_item.outputfiletype,
                                                  'download_file_data': select_item.downloadfiledata
                                                  }})
                    
                    print("Failed: File could not be saved to output folder.")
                    return Response(status=status.HTTP_206_PARTIAL_CONTENT, data={"status": status.HTTP_206_PARTIAL_CONTENT, "details": "File could not be saved to output folder."})
                
                print("Failed: Response could not be obtained.")
                return Response(status=status.HTTP_204_NO_CONTENT, data={"status": status.HTTP_204_NO_CONTENT, "details": "Response could not be obtained."})
            
            print("Failed: DocID not found in the database.")
            return Response(status=status.HTTP_404_NOT_FOUND, data={"status": status.HTTP_404_NOT_FOUND, "details": "DocID not found in the database."})
        
        except Exception as e:
            print("Exception encountered")
            print("*"*20)
            print(e)

            exception_name = type(e).__name__
            return Response(status=status.HTTP_400_BAD_REQUEST, data={"status": status.HTTP_400_BAD_REQUEST, "details": "Exception encountered: " + str(exception_name)})
        