import json
from django.utils.decorators import method_decorator
from rest_framework.views import APIView
from zipfile import ZipFile
from collaborators import defined_roles as dr
from rest_framework import status
from doc_parser.utils.section_separator_utils import (
    split_xmls_element_to_questions_with_answers,
)
from doc_parser.utils.xml_utils import xml_to_element_list
from doc_parser.validators import json_data_parser_input_data_validator
from public_resources.models import PublicResource
from utils.myresponse import MyResponse
from django.utils.decorators import decorator_from_middleware_with_args
from doc_parser.serializers import JsonParserInputSerializer, DocParserInputSerializer
from institute.models import Institute
from wikiazma.middleware import SerializerValidationMiddleware
from collaborators.middleware import CollaborationAccessMiddleware
from authenticate.middleware import AuthorizatorMiddleware
from public_resources.conf import allowed_formats_for_image
from django.core.files.base import ContentFile
from bs4 import BeautifulSoup

serializer_validation_middleware = decorator_from_middleware_with_args(
    SerializerValidationMiddleware
)
user_token_or_server_token_or_server_API_key_validation_and_authorization = (
    decorator_from_middleware_with_args(AuthorizatorMiddleware)
)

check_access_permission_middleware = decorator_from_middleware_with_args(
    CollaborationAccessMiddleware
)


@method_decorator(
    user_token_or_server_token_or_server_API_key_validation_and_authorization(
        accept_user_token=True
    ),
    name="post",
)
@method_decorator(
    serializer_validation_middleware(DocParserInputSerializer), name="post"
)
@method_decorator(
    check_access_permission_middleware(
        [dr.__PERMISSION_WRITE_QUESTION__], Institute, "id", "context_institute_id"
    ),
    name="post",
)
class DocParserApi(APIView):
    def save_element_images(self, document, elements, caller):
        for element in elements:
            if element["type"] == "img" and element["value"].endswith(
                allowed_formats_for_image
            ):
                image_bytes = document.read("word/" + element["value"], pwd=None)

                public_resource = PublicResource.objects.create(
                    user=caller,
                    title=element["value"],
                    file_type="image",
                    file=ContentFile(image_bytes, name=element["value"].split("/")[-1]),
                )

                element["value"] = public_resource.file.url

    def post(self, request):
        questions_docx = request.middleware_serializer_data.get("questions_docx")
        answers_docx = request.middleware_serializer_data.get("answers_docx")
        skip_images = request.middleware_serializer_data.get("skip_images")

        try:
            question_document = ZipFile(questions_docx)

            question_document_xml_str = question_document.read(
                "word/document.xml", pwd=None
            )
            question_document_rel_str = question_document.read(
                "word/_rels/document.xml.rels", pwd=None
            )

            question_elements = xml_to_element_list(
                question_document_xml_str,
                question_document_rel_str,
                skip_images=skip_images,
            )

            if skip_images is False:
                self.save_element_images(
                    document=question_document,
                    elements=question_elements,
                    caller=request.middleware_user,
                )

            if answers_docx:
                answer_document = ZipFile(answers_docx)

                answer_document_xml_str = answer_document.read(
                    "word/document.xml", pwd=None
                )
                answer_document_rel_str = answer_document.read(
                    "word/_rels/document.xml.rels", pwd=None
                )

                answer_elements = xml_to_element_list(
                    answer_document_xml_str, answer_document_rel_str
                )

                if skip_images is False:
                    self.save_element_images(
                        document=answer_document,
                        elements=answer_elements,
                        caller=request.middleware_user,
                    )
            else:
                answer_elements = None
            output = split_xmls_element_to_questions_with_answers(
                question_elements, answer_elements
            )

            return MyResponse(
                request,
                {"status": "ok", "message": "Successful", "data": output},
                status=status.HTTP_200_OK,
            )

        except:
            return MyResponse(
                request,
                {"status": "error", "message": "BadRequest"},
                status=status.HTTP_400_BAD_REQUEST,
            )


@method_decorator(
    user_token_or_server_token_or_server_API_key_validation_and_authorization(
        accept_user_token=True
    ),
    name="post",
)
@method_decorator(
    serializer_validation_middleware(JsonParserInputSerializer), name="post"
)
@method_decorator(
    check_access_permission_middleware(
        [dr.__PERMISSION_WRITE_QUESTION__], Institute, "id", "context_institute_id"
    ),
    name="post",
)
class JsonParserApi(APIView):
    def localized_html_resource(self, html, document, caller):
        soup = BeautifulSoup(html, features="html.parser")
        # output = html
        imgs = soup.find_all("img")
        for img in imgs:
            src = img["src"]
            if src.startswith("data:image"):
                continue
            image_bytes = document.read("" + src, pwd=None)
            image_name = src.split("/")[-1]

            public_resource = PublicResource.objects.create(
                user=caller,
                title=image_name,
                file_type="image",
                file=ContentFile(image_bytes, name=image_name),
            )
            img["src"] = public_resource.file.url
            # import re
            # output = re.sub(src, public_resource.file.url, html)
            # output = html.replace(src, public_resource.file.url)

        # return output
        return str(soup)

    def post(self, request):
        zip_file = request.middleware_serializer_data.get("zip_file")
        caller = request.middleware_user

        document = ZipFile(zip_file)

        json_data_str = document.read("data.json", pwd=None)
        json_data = json.loads(json_data_str)
        if json_data_parser_input_data_validator(json_data):
            output = []
            for item in json_data:
                try:
                    item["question"]["html"] = self.localized_html_resource(
                        html=item["question"]["html"], document=document, caller=caller
                    )
                    if item.get("answer"):
                        item["answer"]["html"] = (
                            self.localized_html_resource(
                                html=item["answer"]["html"],
                                document=document,
                                caller=caller,
                            )
                            if item["answer"]["html"]
                            else None
                        )
                    if item.get("choices"):
                        for choice in item["choices"]:
                            choice["html"] = self.localized_html_resource(
                                html=choice["html"], document=document, caller=caller
                            )
                    output.append(item)
                except:
                    pass

            return MyResponse(
                request,
                {"status": "success", "data": json_data},
                status=status.HTTP_200_OK,
            )
