from __future__ import annotations

import logging

import yaml

from app.core.rag.indexing.docs.chunkers.markdown_chunker import SectionChunk
from app.core.rag.indexing.docs.models import IntegrationRecord

LOGGER = logging.getLogger(__name__)


class DocsIntegrationExtractor:
    _SECTION_TITLES = {"integrations", "интеграции"}

    def extract(self, sections: list[SectionChunk], *, path: str = "") -> list[IntegrationRecord]:
        records: list[IntegrationRecord] = []
        for section in sections:
            if not self._is_integration_section(section.section_path):
                continue
            payload = self._payload(section.content, path=path, section_path=section.section_path)
            target = str(payload.get("target") or "").strip()
            if not target:
                continue
            details = payload.get("details")
            if not isinstance(details, dict):
                details = {}
            records.append(
                IntegrationRecord(
                    name=section.section_title,
                    target=target,
                    target_type=str(payload.get("target_type") or "").strip(),
                    direction=str(payload.get("direction") or "").strip(),
                    interaction=str(payload.get("interaction") or "").strip(),
                    via=str(payload.get("via") or "").strip(),
                    purpose=str(payload.get("purpose") or "").strip(),
                    details=details,
                    anchor=section.section_path,
                )
            )
        return records

    def _is_integration_section(self, section_path: str) -> bool:
        parts = [item.strip().lower() for item in section_path.split(" > ") if item.strip()]
        return any(part in self._SECTION_TITLES for part in parts[:-1]) or (parts and parts[-1] in self._SECTION_TITLES)

    def _payload(self, text: str, *, path: str, section_path: str) -> dict:
        payload: dict = {}
        details_lines: list[str] = []
        collecting_details = False
        for raw_line in text.splitlines():
            if not raw_line.strip():
                continue
            indent = len(raw_line) - len(raw_line.lstrip(" "))
            stripped = raw_line.strip()
            if indent > 0 and collecting_details:
                details_lines.append(raw_line)
                continue
            if not stripped.startswith("- "):
                continue
            key, value = self._split_key_value(stripped[2:])
            if not key:
                continue
            if key == "details":
                collecting_details = True
                details_lines = []
                if value:
                    payload[key] = self._yaml_value(
                        value,
                        path=path,
                        section_path=section_path,
                        field_name=key,
                        fallback="",
                    )
                continue
            collecting_details = False
            payload[key] = self._yaml_value(
                value,
                path=path,
                section_path=section_path,
                field_name=key,
                fallback=value,
            )
        if details_lines:
            payload["details"] = self._details_payload(details_lines, path=path, section_path=section_path)
        return payload

    def _details_payload(self, lines: list[str], *, path: str, section_path: str) -> dict:
        normalized: list[str] = []
        for raw_line in lines:
            line = raw_line[2:] if raw_line.startswith("  ") else raw_line
            stripped = line.lstrip()
            indent = len(line) - len(stripped)
            if indent == 0 and stripped.startswith("- "):
                stripped = stripped[2:]
            normalized.append((" " * indent) + stripped)
        payload = self._yaml_value(
            "\n".join(normalized),
            path=path,
            section_path=section_path,
            field_name="details",
            fallback={},
        ) or {}
        return payload if isinstance(payload, dict) else {}

    def _split_key_value(self, text: str) -> tuple[str, str]:
        if ":" not in text:
            return text.strip(), ""
        key, value = text.split(":", 1)
        return key.strip(), value.strip()

    def _yaml_value(self, value: str, *, path: str, section_path: str, field_name: str, fallback):
        if not value:
            return ""
        try:
            return yaml.safe_load(value)
        except yaml.YAMLError as exc:
            LOGGER.warning(
                "docs integration parse warning: path=%s section=%s field=%s reason=%s",
                path or "<unknown>",
                section_path,
                field_name,
                exc.__class__.__name__,
            )
            return fallback
