import platform
from datetime import datetime
from enum import IntEnum

from .report_template import *


class TestResult(IntEnum):
    Unknown = -1
    Passed = 0
    Failed = 1
    Skipped = 2
    Aborted = 3


class TestAdditionalInfo:

    def __init__(self, dut_model_name: str = "", dut_revision: str = "", dut_serial_number: str = "",
                 dut_firmware_version: str = "", dut_driver_version: str = "", tested_by: str = "", remarks: str = ""):
        self.device_name = str()
        self.device_serial_number = str()
        self.device_detailed_data = str()
        self.device_frontend_version = str()
        self.memory_size = str()
        self.python_version = platform.python_version()
        self.bundle_version = str()
        self.dut_model_name = dut_model_name
        self.dut_revision = dut_revision
        self.dut_serial_number = dut_serial_number
        self.dut_firmware_version = dut_firmware_version
        self.dut_driver_version = dut_driver_version
        self.tested_by = tested_by
        self.remarks = remarks


def write_to_file(file_name, text: str):
    with open(file_name, 'w', encoding='UTF-8') as file:
        file.write(text)


def replace_additional_info(test_additional_info: TestAdditionalInfo):
    result = DeviceDescription

    result = result.replace("#device_name#", test_additional_info.device_name)
    result = result.replace("#detailed_vdata#", test_additional_info.device_detailed_data)
    result = result.replace("#frontend_version#", test_additional_info.device_frontend_version)
    result = result.replace("#memory_size#", test_additional_info.memory_size)
    result = result.replace("#console_app_version#", test_additional_info.python_version)
    result = result.replace("#console_bundle_version#", test_additional_info.bundle_version)
    result = result.replace("#date_time#", datetime.now().strftime("%d-%m-%Y %H:%M"))
    result = result.replace("#model_name#", test_additional_info.dut_model_name)
    result = result.replace("#revision#", test_additional_info.dut_revision)
    result = result.replace("#serial_number#", test_additional_info.dut_serial_number)
    result = result.replace("#firmware_version#", test_additional_info.dut_firmware_version)
    result = result.replace("#driver_version#", test_additional_info.dut_driver_version)
    result = result.replace("#conducted_by#", test_additional_info.tested_by)
    result = result.replace("#remarks#", test_additional_info.remarks)

    return result


def generate_html_report(path: str, test_additional_info: TestAdditionalInfo, reports: list):
    result = str()

    head = ReportHead
    head = head.replace("#count#", str((len(reports) + 2)))

    body = ReportBody
    body = body.replace("#device_description#", replace_additional_info(test_additional_info))

    runs = 0
    failed = 0
    skipped = 0
    aborted = 0

    dict_result_2 = {TestResult.Failed: "FAILED",
                     TestResult.Skipped: "SKIPPED",
                     TestResult.Aborted: "ABORTED",
                     TestResult.Passed: "PASSED"}

    json_config_info = '[' + ",".join(f'"{report.json_config_info}"' for report in reports) + ']'

    for item in reports:
        runs += 1
        if item.test_result == TestResult.Failed:
            failed += 1
        elif item.test_result == TestResult.Skipped:
            skipped += 1
        elif item.test_result == TestResult.Aborted:
            aborted += 1

    head = head.replace("#configInfo#", json_config_info)
    result += head

    passed = runs - failed - skipped - aborted

    body = body.replace("#runs#", str(runs))
    body = body.replace("#passed#", str(passed))
    body = body.replace("#failed#", str(failed))
    body = body.replace("#skipped#", str(skipped))
    body = body.replace("#aborted#", str(aborted))

    options_list = ""
    for i in range(len(reports)):
        line = OptionListLine
        line = line.replace("#number#", str(i + 2))
        line = line.replace("#test_name#", f"{reports[i].group_name} / {reports[i].test_name}")
        line = line.replace("#test_result#", dict_result_2.get(reports[i].test_result))
        options_list += line + "\n"

    body = body.replace("#optionList#", options_list)

    tables = Tables
    table_lines = ""
    for i in range(len(reports)):
        line = TestDescriptionLine
        line = line.replace("#handler_number#", str(i + 2))
        line = line.replace("#test_name#", reports[i].test_name)
        line = line.replace("#test_group#", reports[i].group_name)
        line = line.replace("#test_result#", dict_result_2.get(reports[i].test_result))
        line = line.replace("#error#", f"{reports[i].error_code}" if reports[i].error_code != 0 else "-")
        line = line.replace("#ending#", "2" if i % 2 else "")
        test_result = dict_result_2.get(reports[i].test_result)
        line = line.replace("#SUCCESS#", test_result if test_result is not None else "PASSED")
        table_lines += line + "\n"

    tables = tables.replace("#test_description_lines#", table_lines)

    def escape_html(log: str) -> str:
        res = []

        for c in log:
            if c == '&':
                res.append("&amp;")
            elif c == '<':
                res.append("&lt;")
            elif c == '>':
                res.append("&gt;")
            elif c == '"':
                res.append("&quot;")
            elif c == '\'':
                res.append("&apos;")
            else:
                res.append(c)

        return ''.join(res)

    tables_list = ""
    warnings = ""
    for i in range(len(reports)):
        line = TestTable
        line = line.replace("#number#", f"{i + 2}")
        line = line.replace("#test_number#", f"{i + 1}")
        line = line.replace("#test_group#", reports[i].group_name)
        line = line.replace("#test_name#", reports[i].test_name)
        line = line.replace("#result#", dict_result_2.get(reports[i].test_result))
        line = line.replace("#test_delay#", f"{reports[i].test_delay * 1000}")
        line = line.replace("#test_parameters#", reports[i].config_info)
        line = line.replace("#warning#", "<b>Debug options enabled!</b><br><br>" if reports[i].debug else "")

        if reports[i].debug:
            warnings = "<b>Debug options enabled!</b><br><br>"

        line = line.replace("#test_log#", escape_html(reports[i].fw_logs))
        tables_list += line + "\n"

    body = body.replace("#warning#", warnings)
    tables = tables.replace("#test_tables_list#", tables_list)
    tables = tables.replace("#warning#", warnings)

    result += body
    result += tables

    footer = ReportFooter
    footer = footer.replace("#result#", "PASSED" if failed == 0 else "FAILED")
    result += footer

    full_name = path if path.lower().find(".html") != -1 else (path + ".html")
    write_to_file(full_name, result)
