import xml.etree.ElementTree as ET
from collections.abc import Callable
from dataclasses import dataclass
from datetime import datetime
from enum import StrEnum, auto
from xml.dom import minidom

ACCOUNT_INFO = [
    "Account",
    "Make",
    "Site",
    "Origin",
    "SalesChannel",
    "CostCarrier",
    "CostAccountingString",
]


class GchrExportFormat(StrEnum):
    SKR51 = auto()
    Volkswagen = auto()
    Opel = auto()


@dataclass
class GchrExportConfig:
    main_site: str
    current_year: str
    current_month: str
    makes_used: dict[str, str]
    sites_used: dict[str, str]
    first_month: str
    period_no: str
    bookkeep_filter: dict[str, str]
    extraction_date: datetime
    export_file: str
    bookkeep_records = dict[str, list[str]]


def export_skr51_xml(export_cfg: GchrExportConfig):
    record_elements = (
        ACCOUNT_INFO
        + ["Decimals"]
        + list(export_cfg.bookkeep_filter.values())[: export_cfg.period_no]
        + ["CumulatedYear"]
    )
    root = ET.Element("HbvData")
    h = ET.SubElement(root, "Header")
    for k, v in export_skr51_header(export_cfg).items():
        ET.SubElement(h, k).text = str(v)

    make_list = ET.SubElement(root, "MakeList")
    for make, make_code in export_cfg.makes_used.items():
        e = ET.SubElement(make_list, "MakeListEntry")
        ET.SubElement(e, "Make").text = make
        ET.SubElement(e, "MakeCode").text = make_code

    bm_code_list = ET.SubElement(root, "BmCodeList")
    for s, bmcode in export_cfg.sites_used.items():
        make, site = s.split("-")
        e = ET.SubElement(bm_code_list, "BmCodeEntry")
        ET.SubElement(e, "Make").text = make
        ET.SubElement(e, "Site").text = site
        ET.SubElement(e, "BmCode").text = bmcode

    record_list = ET.SubElement(root, "RecordList")
    for row in export_cfg.bookkeep_records:
        record = ET.SubElement(record_list, "Record")
        for e in record_elements:
            child = ET.SubElement(record, e)
            field = row.get(e, 0.0)
            if str(field) == "nan":
                field = "0"
            elif type(field) is float:
                field = "{:.0f}".format(field * 100)
            child.text = str(field)

    with open(export_cfg.export_file, "w", encoding="utf-8") as fwh:
        fwh.write(minidom.parseString(ET.tostring(root)).toprettyxml(indent="  "))


def export_skr51_header(export_cfg: GchrExportConfig) -> dict[str, str]:
    return {
        "Country": "DE",
        "MainBmCode": export_cfg.main_site,
        "Month": export_cfg.current_month,
        "Year": export_cfg.current_year,
        "Currency": "EUR",
        "NumberOfMakes": len(export_cfg.makes_used),
        "NumberOfSites": len(export_cfg.sites_used),
        "ExtractionDate": export_cfg.extraction_date.strftime("%d.%m.%Y"),
        "ExtractionTime": export_cfg.extraction_date.strftime("%H:%M:%S"),
        "BeginFiscalYear": export_cfg.first_month,
    }


GchrExportFn = Callable[[GchrExportConfig], None]


EXPORT_FN: dict[GchrExportFormat, GchrExportFn] = {
    GchrExportFormat.SKR51: export_skr51_xml,
}


def export_dummy(export_cfg: GchrExportConfig) -> None:
    pass


def get_export_fn(export_format: GchrExportFormat) -> GchrExportFn:
    return EXPORT_FN.get(export_format, export_dummy)