from __future__ import annotations

import re


class DocsFactExtractor:
    def extract(self, frontmatter: dict, sections) -> list[dict]:
        subject_id = str(frontmatter.get("id") or "")
        facts: list[dict] = []
        for entity in frontmatter.get("entities") or []:
            value = str(entity or "").strip()
            if value:
                facts.append(self._fact(subject_id, "mentions_entity", value, "frontmatter.entities"))
        for section in sections:
            facts.extend(self._facts_from_table(subject_id, section.section_title, section.content))
            facts.extend(self._facts_from_lists(subject_id, section.section_title, section.content))
        return facts

    def _fact(self, subject_id: str, predicate: str, obj: str, anchor: str, object_ref: str | None = None) -> dict:
        return {"subject_id": subject_id, "predicate": predicate, "object": obj, "object_ref": object_ref, "anchor": anchor}

    def _facts_from_table(self, subject_id: str, title: str, content: str) -> list[dict]:
        lines = [line.strip() for line in content.splitlines() if line.strip()]
        if len(lines) < 3 or "|" not in lines[0]:
            return []
        headers = [part.strip().lower() for part in lines[0].strip("|").split("|")]
        facts: list[dict] = []
        for row in lines[2:]:
            if "|" not in row:
                continue
            values = [part.strip() for part in row.strip("|").split("|")]
            if len(values) != len(headers):
                continue
            payload = dict(zip(headers, values))
            facts.extend(self._facts_from_row(subject_id, title, payload))
        return facts

    def _facts_from_row(self, subject_id: str, title: str, payload: dict) -> list[dict]:
        facts: list[dict] = []
        lowered = title.lower()
        name = payload.get("field") or payload.get("name") or payload.get("column") or payload.get("code")
        if name and ("входные параметры" in lowered or "выходные параметры" in lowered or "contract" in lowered):
            facts.append(self._fact(subject_id, "has_field", name, title))
            if payload.get("type"):
                facts.append(self._fact(subject_id, "field_type", f"{name}:{payload['type']}", title))
            if payload.get("обязательность") or payload.get("required"):
                required = payload.get("обязательность") or payload.get("required")
                facts.append(self._fact(subject_id, "field_required", f"{name}:{required}", title))
        if "ошиб" in lowered or "error" in lowered:
            if payload.get("status"):
                facts.append(self._fact(subject_id, "returns_status", payload["status"], title))
            if payload.get("error") or payload.get("code"):
                facts.append(self._fact(subject_id, "returns_error", payload.get("error") or payload.get("code"), title))
        return facts

    def _facts_from_lists(self, subject_id: str, title: str, content: str) -> list[dict]:
        facts: list[dict] = []
        for line in content.splitlines():
            item = line.strip()
            if not item.startswith(("-", "*", "1.", "2.", "3.", "4.", "5.")):
                continue
            normalized = re.sub(r"^[-*0-9. ]+", "", item).strip()
            if not normalized:
                continue
            predicate = "workflow_step" if "сценарий" in title.lower() else "doc_list_item"
            facts.append(self._fact(subject_id, predicate, normalized, title))
        return facts
