"""Semantic profiles for 1C managed form XML exports."""

from __future__ import annotations

import xml.etree.ElementTree as ET
from pathlib import Path
from typing import Any


FORM_XML_KIND_RU = {
    "Form": "Форма",
    "Event": "Событие",
    "Attribute": "Реквизит формы",
    "Column": "Колонка реквизита",
    "Command": "Команда формы",
    "AutoCommandBar": "Командная панель",
    "Button": "Кнопка",
    "ButtonGroup": "Группа кнопок",
    "CommandBar": "Командная панель",
    "Popup": "Подменю",
    "Pages": "Страницы",
    "ColumnGroup": "Группа колонок",
    "LabelField": "Поле надписи",
    "InputField": "Поле ввода",
    "CheckBoxField": "Поле флажка",
    "Table": "Таблица",
    "TableColumn": "Колонка таблицы",
    "Page": "Страница",
    "UsualGroup": "Группа",
    "DecorativeLabel": "Декорация надпись",
    "ContextMenu": "Контекстное меню",
    "ExtendedTooltip": "Расширенная подсказка",
    "SearchStringAddition": "Дополнение строки поиска",
    "ViewStatusAddition": "Дополнение состояния просмотра",
    "SearchControlAddition": "Дополнение управления поиском",
}

FORM_XML_PROPERTY_NAMES = {
    "name": "Имя",
    "id": "Идентификатор",
    "Title": "Заголовок",
    "Type": "Вид",
    "DataPath": "ПутьКДанным",
    "TitleLocation": "ПоложениеЗаголовка",
    "Visible": "Видимость",
    "UserVisible": "ПользовательскаяВидимость",
    "Enabled": "Доступность",
    "ReadOnly": "ТолькоПросмотр",
    "SkipOnInput": "ПропускатьПриВводе",
    "DefaultItem": "АктивизироватьПоУмолчанию",
    "Importance": "ВажностьПриОтображении",
    "ServerUnavailabilityBehavior": "ПоведениеПриНедоступностиОсновногоСервера",
    "PasswordMode": "РежимПароля",
    "Hyperlink": "Гиперссылка",
    "CommandName": "ИмяКоманды",
    "WindowOpeningMode": "РежимОткрытияОкна",
    "AutoSaveDataInSettings": "АвтоСохранениеДанныхВНастройках",
    "CommandBarLocation": "ПоложениеКоманднойПанели",
    "ShowCommandBar": "ОтображатьКоманднуюПанель",
    "AutoCommandBar": "АвтоКоманднаяПанель",
    "SearchStringAddition": "ДополнениеСтрокиПоиска",
    "ViewStatusAddition": "ДополнениеСостоянияПросмотра",
    "SearchControlAddition": "ДополнениеУправленияПоиском",
    "Representation": "Отображение",
    "ChangeRowSet": "ИзменятьСоставСтрок",
    "RowSelectionMode": "РежимВыделенияСтроки",
    "HorizontalLinesBWA": "ГоризонтальныеЛинии",
    "VerticalLinesBWA": "ВертикальныеЛинии",
    "UseAlternationRowColorBWA": "ЧередованиеЦветовСтрок",
    "AutoInsertNewRow": "АвтоВставкаНовойСтроки",
    "EnableStartDrag": "РазрешитьНачалоПеретаскивания",
    "EnableDrag": "РазрешитьПеретаскивание",
    "RowFilter": "ОтборСтрок",
    "HeightInTableRows": "ВысотаВСтрокахТаблицы",
    "Footer": "Подвал",
    "FileDragMode": "РежимПеретаскиванияФайлов",
    "SearchStringLocation": "ПоложениеСтрокиПоиска",
    "ViewStatusLocation": "ПоложениеСостоянияПросмотра",
    "SearchControlLocation": "ПоложениеУправленияПоиском",
    "ButtonGroup": "СоставКоманд",
    "Group": "Группировка",
    "Behavior": "Поведение",
    "ShowTitle": "ПоказыватьЗаголовок",
    "Autofill": "Автозаполнение",
    "EditWarningRepresentation": "ОтображениеПредупрежденияПриРедактировании",
    "EditWarning": "ПредупреждениеПриРедактировании",
    "EditMode": "РежимРедактирования",
    "AutoEditMode": "АвтоРежимРедактирования",
    "AutoCellHeight": "АвтоВысотаЯчейки",
    "FixInTable": "ФиксацияВТаблице",
    "Shortcut": "СочетаниеКлавиш",
    "CommandSet": "СоставКоманд",
    "UseCopy": "ИспользоватьКопирование",
    "ShowInHeader": "ОтображатьВШапке",
    "ShowInFooter": "ОтображатьВПодвале",
    "ToolTip": "Подсказка",
    "ToolTipRepresentation": "ОтображениеПодсказки",
    "DropListButton": "КнопкаВыпадающегоСписка",
    "ChoiceButton": "КнопкаВыбора",
    "ClearButton": "КнопкаОчистки",
    "SpinButton": "КнопкаРегулирования",
    "OpenButton": "КнопкаОткрытия",
    "CreateButton": "КнопкаСоздания",
    "QuickChoice": "БыстрыйВыбор",
    "ChooseType": "ВыбиратьТип",
    "ChoiceList": "СписокВыбора",
    "IncompleteChoiceMode": "РежимВыбораНезаполненного",
    "TextEdit": "РедактированиеТекста",
    "TextEditUpdate": "ОбновлениеТекстаРедактирования",
    "MultiLine": "МногострочныйРежим",
    "AutoLineBreak": "АвтоПереносСтрок",
    "AutoMarkIncomplete": "АвтоОтметкаНезаполненного",
    "AutoChoiceIncomplete": "АвтоВыборНезаполненного",
    "InputHint": "ПодсказкаВвода",
    "ChoiceHistoryOnInput": "ИсторияВыбораПриВводе",
    "Picture": "Картинка",
    "HeaderPicture": "КартинкаШапки",
    "FooterPicture": "КартинкаПодвала",
    "BackColor": "ЦветФона",
    "TextColor": "ЦветТекста",
    "BorderColor": "ЦветРамки",
    "Font": "Шрифт",
    "Shape": "Фигура",
    "ShapeRepresentation": "ОтображениеФигуры",
    "PictureLocation": "ПоложениеКартинки",
    "HeaderBackColor": "ЦветФонаЗаголовка",
    "Width": "Ширина",
    "Height": "Высота",
    "AutoMaxWidth": "АвтоМаксимальнаяШирина",
    "AutoMaxHeight": "АвтоМаксимальнаяВысота",
    "MaxWidth": "МаксимальнаяШирина",
    "MaxHeight": "МаксимальнаяВысота",
    "TitleHeight": "ВысотаЗаголовка",
    "HorizontalAlign": "ГоризонтальноеПоложениеВГруппе",
    "VerticalAlign": "ВертикальноеПоложениеВГруппе",
    "HorizontalStretch": "РастягиватьПоГоризонтали",
    "VerticalStretch": "РастягиватьПоВертикали",
    "LocationInCommandBar": "ПоложениеВКоманднойПанели",
    "UniqueCommands": "УникальностьКоманд",
    "DefaultButton": "КнопкаПоУмолчанию",
    "Check": "Пометка",
    "MainAttribute": "ОсновнойРеквизит",
    "Action": "Действие",
    "AdditionSource": "ИсточникДополнения",
    "Columns": "Колонки",
    "Save": "СохраняемыеДанные",
    "ContextMenu": "КонтекстноеМеню",
    "ExtendedTooltip": "РасширеннаяПодсказка",
    "Events": "События",
    "Handler": "Обработчик",
    "ChildItems": "ПодчиненныеЭлементы",
}

FORM_XML_PROPERTY_GROUPS = {
    "Основные": {
        "name",
        "id",
        "Title",
        "Type",
        "DataPath",
        "CommandName",
        "WindowOpeningMode",
        "AutoSaveDataInSettings",
        "CommandBarLocation",
        "ShowCommandBar",
        "AutoCommandBar",
        "SearchStringAddition",
        "ViewStatusAddition",
        "SearchControlAddition",
        "TitleLocation",
        "Visible",
        "UserVisible",
        "Enabled",
        "ReadOnly",
        "SkipOnInput",
        "DefaultItem",
        "Importance",
        "ServerUnavailabilityBehavior",
        "PasswordMode",
        "Hyperlink",
        "Representation",
        "ButtonGroup",
        "Group",
        "Behavior",
        "ShowTitle",
        "Autofill",
    },
    "Использование": {
        "EditWarningRepresentation",
        "EditWarning",
        "EditMode",
        "AutoEditMode",
        "AutoCellHeight",
        "FixInTable",
        "Shortcut",
        "CommandSet",
        "UseCopy",
        "ChangeRowSet",
        "RowSelectionMode",
        "AutoInsertNewRow",
        "EnableStartDrag",
        "EnableDrag",
        "RowFilter",
        "FileDragMode",
        "ShowInHeader",
        "ShowInFooter",
        "ToolTip",
        "ToolTipRepresentation",
        "DropListButton",
        "ChoiceButton",
        "ClearButton",
        "SpinButton",
        "OpenButton",
        "CreateButton",
        "QuickChoice",
        "ChooseType",
        "ChoiceList",
        "IncompleteChoiceMode",
        "TextEdit",
        "TextEditUpdate",
        "MultiLine",
        "AutoLineBreak",
        "AutoMarkIncomplete",
        "AutoChoiceIncomplete",
        "InputHint",
        "ChoiceHistoryOnInput",
        "MainAttribute",
        "Action",
        "Save",
    },
    "Оформление": {
        "Picture",
        "HeaderPicture",
        "FooterPicture",
        "BackColor",
        "TextColor",
        "BorderColor",
        "Font",
        "Shape",
        "ShapeRepresentation",
        "PictureLocation",
        "HeaderBackColor",
        "Footer",
        "HorizontalLinesBWA",
        "VerticalLinesBWA",
        "UseAlternationRowColorBWA",
    },
    "Расположение": {
        "Width",
        "Height",
        "HeightInTableRows",
        "SearchStringLocation",
        "ViewStatusLocation",
        "SearchControlLocation",
        "AutoMaxWidth",
        "AutoMaxHeight",
        "MaxWidth",
        "MaxHeight",
        "TitleHeight",
        "HorizontalAlign",
        "VerticalAlign",
        "HorizontalStretch",
        "VerticalStretch",
        "LocationInCommandBar",
        "UniqueCommands",
        "DefaultButton",
        "Check",
        "AdditionSource",
        "Columns",
    },
}

FORM_XML_CONTAINER_TAGS = {"ChildItems", "CommandSet", "Events"}


def local_name(tag: str) -> str:
    return tag.rsplit("}", 1)[-1]


def property_group(tag: str) -> str:
    for group, names in FORM_XML_PROPERTY_GROUPS.items():
        if tag in names:
            return group
    return "Прочее"


def xml_scalar(element: ET.Element) -> Any:
    text = (element.text or "").strip()
    if text:
        if text == "true":
            return True
        if text == "false":
            return False
        return text
    if "name" in element.attrib:
        return element.attrib.get("name")
    if "id" in element.attrib:
        return element.attrib.get("id")
    return None


def add_property(groups: dict[str, list[dict[str, Any]]], xml_name: str, value: Any, *, source: str = "form_xml") -> None:
    if value is None:
        return
    group = property_group(xml_name)
    groups.setdefault(group, []).append(
        {
            "name": FORM_XML_PROPERTY_NAMES.get(xml_name, xml_name),
            "xml_name": xml_name,
            "value": value,
            "source": source,
            "status": "ok" if value not in {"", None} else "empty",
        }
    )


def element_semantic(element: ET.Element) -> dict[str, Any]:
    tag = local_name(element.tag)
    groups: dict[str, list[dict[str, Any]]] = {}
    add_property(groups, "name", element.attrib.get("name"), source="form_xml_attribute")
    add_property(groups, "id", element.attrib.get("id"), source="form_xml_attribute")
    add_property(groups, "Type", FORM_XML_KIND_RU.get(tag, tag), source="form_xml_tag")
    if tag == "Event" and (element.text or "").strip():
        add_property(groups, "Handler", (element.text or "").strip(), source="form_xml_text")
    for child in list(element):
        child_tag = local_name(child.tag)
        if child_tag in FORM_XML_CONTAINER_TAGS:
            continue
        add_property(groups, child_tag, xml_scalar(child))
    mapped = sum(len(items) for items in groups.values())
    return {
        "groups": groups,
        "coverage": {
            "mapped": mapped,
            "unmapped": 0,
            "total": mapped,
            "status": "ok",
        },
    }


def walk_form_elements(root: ET.Element, *, limit: int = 5000) -> tuple[list[dict[str, Any]], int, bool]:
    records: list[dict[str, Any]] = []
    total = 0

    def walk(
        element: ET.Element,
        path: list[int],
        additional_columns_table: str | None = None,
        owner_name: str | None = None,
    ) -> None:
        nonlocal total
        tag = local_name(element.tag)
        if tag == "AdditionalColumns" and element.attrib.get("table"):
            additional_columns_table = element.attrib.get("table")
        if "name" in element.attrib:
            total += 1
            if len(records) < limit:
                records.append(
                    {
                        "name": element.attrib.get("name"),
                        "id": element.attrib.get("id"),
                        "kind": tag,
                        "kind_ru": FORM_XML_KIND_RU.get(tag, tag),
                        "xml_path": ".".join(str(part) for part in path),
                        "semantic": element_semantic(element),
                        **({"additional_columns_table": additional_columns_table} if additional_columns_table else {}),
                        **({"owner": owner_name} if tag == "Event" and owner_name else {}),
                    }
                )
        child_owner = element.attrib.get("name") if "name" in element.attrib and tag != "Event" else owner_name
        for index, child in enumerate(list(element)):
            walk(child, [*path, index], additional_columns_table, child_owner)

    walk(root, [])
    return records, total, total > len(records)


def decode_form_xml(xml: str | bytes | Path, *, max_items: int = 5000) -> dict[str, Any]:
    if isinstance(xml, Path):
        root = ET.parse(xml).getroot()
        source = {"kind": "xml_file", "path": str(xml)}
    else:
        root = ET.fromstring(xml)
        source = {"kind": "xml_text"}
    items, total, truncated = walk_form_elements(root, limit=max_items)
    return {
        "schema": "onec_form_xml_profile.v1",
        "status": "ok",
        "source": source,
        "form": {
            "version": root.attrib.get("version"),
            "kind": local_name(root.tag),
            "kind_ru": FORM_XML_KIND_RU.get(local_name(root.tag), local_name(root.tag)),
            "semantic": element_semantic(root),
        },
        "items": items,
        "counts": {
            "items": len(items),
            "items_total": total,
            "items_truncated": truncated,
        },
    }
