"""R source parser (regex-based)."""

from __future__ import annotations

import re

from codectx.parser.types import DependencyRecord, EntityRecord, ParseResult

_LIBRARY_RE  = re.compile(r"""^\s*(?:library|require)\s*\(\s*(?:'([^']+)'|"([^"]+)"|([A-Za-z.]\w*))\s*\)""", re.MULTILINE)
_SOURCE_RE   = re.compile(r"""^\s*source\s*\(\s*(?:'([^']+)'|"([^"]+)")\s*\)""", re.MULTILINE)
_FN_ARROW_RE = re.compile(r"""^(\s*)(\w+)\s*<-\s*function\s*\(""", re.MULTILINE)
_FN_EQ_RE    = re.compile(r"""^(\s*)(\w+)\s*=\s*function\s*\(""", re.MULTILINE)
_SETCLASS_RE = re.compile(r"""setClass\s*\(\s*["'](\w+)["']""", re.MULTILINE)
_SETGENERIC_RE = re.compile(r"""setGeneric\s*\(\s*["'](\w+)["']""", re.MULTILINE)


def _ln(content: str, pos: int) -> int:
    return content[:pos].count("\n") + 1


def parse_r(file_path: str, content: str) -> ParseResult:
    result = ParseResult(file_path=file_path, language="r")

    for m in _LIBRARY_RE.finditer(content):
        pkg = m.group(1) or m.group(2) or m.group(3) or ""
        result.dependencies.append(DependencyRecord(
            path=pkg, type="library", line_number=_ln(content, m.start()),
        ))

    for m in _SOURCE_RE.finditer(content):
        path = m.group(1) or m.group(2) or ""
        result.dependencies.append(DependencyRecord(
            path=path, type="source", line_number=_ln(content, m.start()), is_local=True,
        ))

    seen: set[str] = set()
    for m in _FN_ARROW_RE.finditer(content):
        name = m.group(2)
        if name not in seen:
            seen.add(name)
            result.entities.append(EntityRecord(
                name=name, qualified_name=name, type="function",
                start_line=_ln(content, m.start()), end_line=_ln(content, m.start()),
                language="r",
            ))
    for m in _FN_EQ_RE.finditer(content):
        name = m.group(2)
        if name not in seen:
            seen.add(name)
            result.entities.append(EntityRecord(
                name=name, qualified_name=name, type="function",
                start_line=_ln(content, m.start()), end_line=_ln(content, m.start()),
                language="r",
            ))

    for m in _SETCLASS_RE.finditer(content):
        result.entities.append(EntityRecord(
            name=m.group(1), qualified_name=m.group(1), type="class",
            start_line=_ln(content, m.start()), end_line=_ln(content, m.start()),
            language="r",
        ))

    for m in _SETGENERIC_RE.finditer(content):
        result.entities.append(EntityRecord(
            name=m.group(1), qualified_name=m.group(1), type="function",
            start_line=_ln(content, m.start()), end_line=_ln(content, m.start()),
            language="r",
        ))

    return result
