import pathlib

from werkzeug.utils import secure_filename
from flask import request

from helpers.md_and_html_convertor import MdAndHTMLConvertorLowLevel
from helpers.file_utils import is_whitelisted_extension
from typing import Optional, Union, Set, Tuple
import os


def does_text_contain_custom_escaped_characters(data: bytes):
    text = data.decode(encoding="utf8")
    unescaped_text = MdAndHTMLConvertorLowLevel.reverse_custom_escaping_of_html(text)
    return text != unescaped_text


def save_multiple_uploaded_files(output_folder: str, reserved_filenames: Set[str], allowed_extensions: Set[str]) -> Tuple[str, Set[str]]:
    files = request.files.getlist("file[]")
    output_filenames = set()

    if len(files) == 0:
        return "No files provided?", output_filenames

    pathlib.Path(output_folder).mkdir(exist_ok=True, parents=True)

    for file in files:
        if not file or file.filename == '':
            return "No filename provided?", output_filenames

        filename = secure_filename(file.filename)

        if not is_whitelisted_extension(filename, allowed_extensions):
            return f"Filetype of file {filename} not allowed", output_filenames
        if filename in reserved_filenames:
            return f"Name {filename} is reserved.", output_filenames
        if filename in output_filenames:
            return f"Name {filename} is duplicate.", output_filenames

        is_dangerous_content_allowed = request.form.get("import_dangerous_files", False)
        content = file.stream.read()
        file.stream.seek(0)
        if does_text_contain_custom_escaped_characters(content) and not is_dangerous_content_allowed:
            min_char = min(MdAndHTMLConvertorLowLevel.HTML_TO_RESERVED_CHARS.values()).encode("unicode_escape")
            max_char = max(MdAndHTMLConvertorLowLevel.HTML_TO_RESERVED_CHARS.values()).encode("unicode_escape")

            return f"""File {filename} contains characters that could cause cause XSS (characters range from {min_char} to {max_char}.
            Importer uses them to encode HTML characters so that we can distinguish them in output of Scan2Report.
            If you need to import them (for example you are recovering a backup), check the option "Import custom escaped HTML (possible XSS)".""", output_filenames

        output_filenames.add(filename)
        output_path = os.path.join(output_folder, filename)
        file.save(output_path)

    return "", output_filenames
